1use rhdl::prelude::*;
94
95use crate::broadcast::{BroadcastOut, BroadcastReq};
96use crate::control::{Args, Status};
97use crate::fetch::{FetchOut, FetchReq};
98use crate::ports::{Axis64, Axis256, Axis512, idle256, idle512};
99use crate::share::{ShareOut, ShareReq};
100use crate::fetch::idle_fetch_req;
101use crate::writer::idle_write_req;
102use crate::broadcast::idle_bcast_req;
103use crate::writer::{WriteOut, WriteReq};
104
105pub mod sub {
107 pub const LEADER: u128 = 3;
109 pub const FAST: u128 = 0;
111 pub const SLOW: u128 = 1;
113 pub const VIEW: u128 = 2;
115}
116
117pub mod st {
121 pub const IDLE: u128 = 0;
123 pub const BASES: u128 = 1;
125 pub const L_INIT: u128 = 8;
127 pub const L_WAIT_PROP: u128 = 9;
129 pub const L_BCAST: u128 = 10;
131 pub const F_INIT: u128 = 16;
133 pub const F_POLL_PREP: u128 = 17;
135 pub const F_WAIT_PREP: u128 = 18;
137 pub const F_BC_WC: u128 = 19;
139 pub const F_POLL_WC: u128 = 20;
141 pub const F_WAIT_WC: u128 = 21;
143 pub const F_BC_WM: u128 = 22;
145 pub const F_POLL_WM: u128 = 23;
147 pub const F_WAIT_WM: u128 = 24;
149 pub const DECIDE: u128 = 25;
151 pub const S_INIT: u128 = 32;
153 pub const S_POLL_PREP: u128 = 33;
155 pub const S_WAIT_PREP: u128 = 34;
157 pub const S_SIGN: u128 = 35;
159 pub const S_SIG_WAIT: u128 = 36;
161 pub const S_BC_SIG: u128 = 37;
163 pub const S_BC_VALID: u128 = 38;
165 pub const S_POLL_VALID: u128 = 39;
167 pub const S_WAIT_VALID: u128 = 40;
169 pub const S_VERIFY: u128 = 41;
171 pub const S_VER_SHARE: u128 = 42;
173 pub const S_VERDICT: u128 = 44;
175 pub const S_BC_COMMIT: u128 = 45;
177 pub const S_POLL_COMMIT: u128 = 46;
179 pub const S_WAIT_COMMIT: u128 = 47;
181 pub const V_INIT: u128 = 48;
183 pub const V_BC_VC: u128 = 51;
185 pub const V_BC_VCV: u128 = 52;
187 pub const V_POLL_VCV: u128 = 53;
189 pub const V_WAIT_VCV: u128 = 54;
191 pub const V_POLL_REC: u128 = 55;
193 pub const V_WAIT_REC: u128 = 56;
195 pub const V_CHOOSE: u128 = 57;
197 pub const V_INSTALL: u128 = 63;
199}
200
201#[derive(Clone, Copy, Debug, PartialEq, Digital, Default)]
203pub struct ProtocolIn {
204 pub start: bool,
206 pub args: Args,
208 pub setup_done: bool,
210 pub fetch: FetchOut,
212 pub bcast: BroadcastOut,
214 pub write: WriteOut,
216 pub share: ShareOut,
218 pub input: Axis64,
220 pub output_ready: bool,
222 pub remote_ready: bool,
224 pub sign_ready: bool,
226 pub sig: Axis512,
228 pub verify_ready: bool,
230 pub verdict: Axis64,
232}
233
234#[derive(Clone, Copy, Debug, PartialEq, Digital, Default)]
236pub struct ProtocolOut {
237 pub fetch: FetchReq,
239 pub bcast: BroadcastReq,
241 pub write: WriteReq,
243 pub share: ShareReq,
245 pub share_ready: bool,
247 pub ram_we: bool,
249 pub ram_addr: b5,
251 pub ram_data: [b64; 8],
253 pub input_ready: bool,
255 pub output: Axis256,
257 pub remote: Axis256,
259 pub sign: Axis512,
261 pub sig_ready: bool,
263 pub verify: Axis512,
265 pub verdict_ready: bool,
267 pub status: Status,
269}
270
271#[derive(Clone, Copy, Debug, PartialEq, Digital)]
274pub struct ProtocolState<const N: usize, const G: usize> {
275 pub st: b6,
277 pub sub: b2,
279 pub args: Args,
281 pub n: b5,
283 pub id: b5,
285 pub f: b5,
287 pub quorum: b5,
289 pub qbase: b24,
291 pub mb_prepare: b32,
293 pub mb_will_cert: b32,
295 pub mb_will_commit: b32,
297 pub mb_commit: b32,
299 pub mb_certify_valid: b32,
301 pub mb_certify: b32,
303 pub mb_vc: b32,
305 pub mb_vc_valid: b32,
307 pub mb_newview: b32,
309 pub mb_newview_valid: b32,
311 pub view: b32,
313 pub leader: b5,
315 pub stop: bool,
318 pub seq: b32,
320 pub slot: b4,
322 pub m: b32,
324 pub local_wait: b32,
326 pub issued: bool,
328 pub bc_done: bool,
330 pub wissued: bool,
332 pub second: bool,
334 pub prop: [b32; G],
336 pub prop_valid: [bool; G],
338 pub enq: b4,
340 pub out_sent: bool,
342 pub rem_sent: bool,
344 pub slowed: bool,
346 pub share_beat: b5,
348 pub checked: [bool; N],
350 pub good: b5,
352 pub peer: b5,
354 pub reading: bool,
356 pub vbeats: b2,
358 pub voted_k: b32,
361 pub voted_m: b32,
363 pub voted_phase: b2,
365 pub rec: b5,
367 pub rec_k: [b32; N],
369 pub rec_m: [b32; N],
371 pub rec_ok: [bool; N],
373 pub nv_k: b32,
375 pub nv_m: b32,
377 pub status: Status,
379 pub slot_start: b32,
381}
382
383impl<const N: usize, const G: usize> ProtocolState<N, G> {
384 pub fn idle() -> Self {
386 Self {
387 st: b6(0),
388 sub: b2(0),
389 args: Args::default(),
390 n: b5(0),
391 id: b5(0),
392 f: b5(0),
393 quorum: b5(0),
394 qbase: b24(0),
395 mb_prepare: b32(0),
396 mb_will_cert: b32(0),
397 mb_will_commit: b32(0),
398 mb_commit: b32(0),
399 mb_certify_valid: b32(0),
400 mb_certify: b32(0),
401 mb_vc: b32(0),
402 mb_vc_valid: b32(0),
403 mb_newview: b32(0),
404 mb_newview_valid: b32(0),
405 view: b32(0),
406 leader: b5(0),
407 stop: false,
408 seq: b32(0),
409 slot: b4(0),
410 m: b32(0),
411 local_wait: b32(0),
412 issued: false,
413 bc_done: false,
414 wissued: false,
415 second: false,
416 prop: [b32(0); G],
417 prop_valid: [false; G],
418 enq: b4(0),
419 out_sent: false,
420 rem_sent: false,
421 slowed: false,
422 share_beat: b5(0),
423 checked: [false; N],
424 good: b5(0),
425 peer: b5(0),
426 reading: false,
427 vbeats: b2(0),
428 voted_k: b32(0),
429 voted_m: b32(0),
430 voted_phase: b2(0),
431 rec: b5(0),
432 rec_k: [b32(0); N],
433 rec_m: [b32(0); N],
434 rec_ok: [false; N],
435 nv_k: b32(0),
436 nv_m: b32(0),
437 status: Status::default(),
438 slot_start: b32(0),
439 }
440 }
441}
442
443#[kernel]
446pub fn vote_tag(view: b32, k: b32) -> b32 {
447 ((view & b32(0xff)) << b32(24)) | (k & b32(0xff_ffff))
448}
449
450#[kernel]
452pub fn fresh_status() -> Status {
453 Status {
454 finished: false,
455 shape: b32(0),
456 decided: b32(0),
457 fast: b32(0),
458 slow: b32(0),
459 views: b32(0),
460 cycles: b32(0),
461 first: b32(0),
462 last: b32(0),
463 slot_min: b32(0),
464 slot_max: b32(0),
465 slot_sum: b64(0),
466 verified: b32(0),
467 rejected: b32(0),
468 state: b32(0),
469 fault: b32(0),
470 }
471}
472
473#[kernel]
475pub fn count_votes(words: [b32; 32], n: b5, tag: b32, m: b32) -> b5 {
476 let mut c = b5(0);
477 for i in 0..16 {
478 if b5(i as u128) < n && words[2 * i] == tag && words[2 * i + 1] == m {
479 c = c + b5(1);
480 }
481 }
482 c
483}
484
485#[kernel]
487pub fn count_flags(words: [b32; 32], n: b5, tag: b32) -> b5 {
488 let mut c = b5(0);
489 for i in 0..16 {
490 if b5(i as u128) < n && words[i] == tag {
491 c = c + b5(1);
492 }
493 }
494 c
495}
496
497#[kernel]
500pub fn choose<const N: usize>(m: [b32; N], ok: [bool; N], f: b5) -> (bool, b32) {
501 let mut found = false;
502 let mut pick = b32(0);
503 for a in 0..N {
504 let mut support = b5(0);
505 for b in 0..N {
506 if ok[a] && ok[b] && m[a] == m[b] {
507 support = support + b5(1);
508 }
509 }
510 if !found && support > f {
511 found = true;
512 pick = m[a];
513 }
514 }
515 (found, pick)
516}
517
518#[allow(clippy::too_many_lines)]
520#[kernel]
521pub fn protocol_kernel<const N: usize, const G: usize, const SB: usize>(
522 i: ProtocolIn,
523 r: ProtocolState<N, G>,
524) -> (ProtocolOut, ProtocolState<N, G>) {
525 let mut s = r;
526 let mut o = ProtocolOut {
527 fetch: idle_fetch_req(),
528 bcast: idle_bcast_req(),
529 write: idle_write_req(),
530 share: ShareReq { start: false, base: b64(0), word: b32(0), beats: b5(0) },
531 share_ready: false,
532 ram_we: false,
533 ram_addr: b5(0),
534 ram_data: [b64(0); 8],
535 input_ready: false,
536 output: idle256(),
537 remote: idle256(),
538 sign: idle512(),
539 sig_ready: false,
540 verify: idle512(),
541 verdict_ready: false,
542 status: r.status,
543 };
544 let sb32 = b32(SB as u128);
545 let base = r.args.network_ptr;
546 let k = r.seq + b32(1);
547 let tag = vote_tag(r.view, k);
548 let slot32: b32 = r.slot.resize();
549 let n32: b32 = r.n.resize();
550 let id32: b32 = r.id.resize();
551 let running = r.st != b6(st::IDLE);
552
553 let mut stop = false;
556 let mut fault = r.status.fault;
557 if running {
558 s.status.cycles = r.status.cycles + b32(1);
559 if r.status.cycles + b32(1) >= r.args.execution_cycles {
560 stop = true;
561 }
562 if r.seq >= b32(0xff_fffe) || r.view >= b32(0xff) {
565 stop = true;
566 fault = fault | b32(2);
567 }
568 }
569 if r.status.finished {
570 s.status.finished = false;
571 }
572
573 let mut enq_free = false;
575 for g in 0..G {
576 if r.enq == b4(g as u128) && !r.prop_valid[g] {
577 enq_free = true;
578 }
579 }
580 o.input_ready = running && enq_free;
581 if running && enq_free && i.input.valid {
582 for g in 0..G {
583 if r.enq == b4(g as u128) {
584 s.prop[g] = i.input.data.resize();
585 s.prop_valid[g] = true;
586 }
587 }
588 s.enq = if r.enq + b4(1) == b4(G as u128) { b4(0) } else { r.enq + b4(1) };
589 }
590 let mut prop_here = false;
591 let mut prop_value = b32(0);
592 for g in 0..G {
593 if r.slot == b4(g as u128) {
594 prop_here = r.prop_valid[g];
595 prop_value = r.prop[g];
596 }
597 }
598
599 let even = (i.args.node_num & b32(1)) == b32(0);
607 let bad_args = i.args.node_num == b32(0) || i.args.node_num > b32(N as u128) || i.args.id >= i.args.node_num || even;
608 if r.st == b6(st::IDLE) && i.start && bad_args {
609 s.status = fresh_status();
610 s.status.finished = true;
611 fault = b32(1);
613 }
614 if r.st == b6(st::IDLE) && i.start && !bad_args {
615 s.status = fresh_status();
616 fault = b32(0);
617 s.seq = b32(0);
618 s.slot = b4(0);
619 s.view = b32(0);
620 s.enq = b4(0);
621 for g in 0..G {
622 s.prop_valid[g] = false;
623 }
624 s.issued = false;
625 s.bc_done = false;
626 s.wissued = false;
627 s.second = false;
628 s.out_sent = false;
629 s.rem_sent = false;
630 s.args = i.args;
631 s.n = i.args.node_num.resize();
632 s.id = i.args.id.resize();
633 s.st = b6(st::BASES);
634 }
635 if r.st == b6(st::BASES) && i.setup_done {
636 let g32 = b32(G as u128);
637 let gn = g32 * n32;
638 s.f = (r.n - b5(1)) >> b5(1);
639 s.quorum = (((r.n - b5(1)) >> b5(1)) << b5(1)) + b5(1);
640 s.qbase = (r.id.resize::<24>()) * ((r.n - b5(1)).resize::<24>());
642 let base0 = b32(250_191);
646 s.mb_prepare = base0;
647 s.mb_will_cert = base0 + g32 * b32(4);
648 s.mb_will_commit = base0 + g32 * b32(4) + gn * b32(2);
649 s.mb_commit = base0 + g32 * b32(4) + gn * b32(4);
650 s.mb_certify_valid = base0 + g32 * b32(4) + gn * b32(6);
651 s.mb_certify = base0 + g32 * b32(4) + gn * b32(8);
652 let vc = base0 + g32 * b32(4) + gn * b32(8) + gn * b32(16) * sb32;
653 s.mb_vc = vc;
654 s.mb_vc_valid = vc + n32 * b32(4);
655 s.mb_newview = vc + n32 * b32(5);
656 s.mb_newview_valid = vc + n32 * b32(5) + b32(4);
657 s.leader = b5(0);
658 s.st = if r.id == b5(0) { b6(st::L_INIT) } else { b6(st::F_INIT) };
659 s.sub = if r.id == b5(0) { b2(sub::LEADER) } else { b2(sub::FAST) };
660 }
661
662 let slot_n = slot32 * n32;
664 let my_vote = slot_n + id32;
665 let peers = r.n - b5(1);
666 let n2: b6 = r.n.resize::<6>() << b6(1);
667
668 if r.st == b6(st::L_INIT) {
670 s.local_wait = b32(0);
671 s.slowed = false;
672 s.voted_phase = b2(0);
673 s.slot_start = r.status.cycles;
674 s.st = b6(st::L_WAIT_PROP);
675 }
676 if r.st == b6(st::L_WAIT_PROP) && prop_here {
677 s.m = prop_value;
678 s.st = b6(st::L_BCAST);
679 }
680
681 if r.st == b6(st::F_INIT) {
683 s.local_wait = b32(0);
684 s.slowed = false;
685 s.voted_phase = b2(0);
686 s.slot_start = r.status.cycles;
687 s.st = b6(st::F_POLL_PREP);
688 }
689
690 let poll_states = (r.st == b6(st::F_POLL_PREP))
693 || (r.st == b6(st::F_POLL_WC))
694 || (r.st == b6(st::F_POLL_WM))
695 || (r.st == b6(st::S_POLL_PREP))
696 || (r.st == b6(st::S_POLL_VALID))
697 || (r.st == b6(st::S_POLL_COMMIT))
698 || (r.st == b6(st::V_POLL_VCV))
699 || (r.st == b6(st::V_POLL_REC));
700 let mut fword = b32(0);
701 let mut fcount = n2;
702 if r.st == b6(st::F_POLL_PREP) || r.st == b6(st::S_POLL_PREP) {
703 fword = r.mb_prepare + (slot32 << b32(2));
704 fcount = b6(4);
705 }
706 if r.st == b6(st::F_POLL_WC) {
707 fword = r.mb_will_cert + (slot_n << b32(1));
708 }
709 if r.st == b6(st::F_POLL_WM) {
710 fword = r.mb_will_commit + (slot_n << b32(1));
711 }
712 if r.st == b6(st::S_POLL_VALID) {
713 fword = r.mb_certify_valid + (slot_n << b32(1));
714 }
715 if r.st == b6(st::S_POLL_COMMIT) {
716 fword = r.mb_commit + (slot_n << b32(1));
717 }
718 if r.st == b6(st::V_POLL_VCV) {
719 fword = r.mb_vc_valid;
720 fcount = r.n.resize();
721 }
722 if r.st == b6(st::V_POLL_REC) {
723 fword = r.mb_vc + (r.rec.resize::<32>() << b32(2));
724 fcount = b6(4);
725 }
726 if poll_states && !i.fetch.busy {
727 o.fetch = FetchReq { start: true, base: base, word: fword, count: fcount };
728 s.st = r.st + b6(1);
729 }
730 let w = i.fetch.words;
731 let got = i.fetch.done;
732 let timed_out = r.local_wait + b32(1) > r.args.wait;
734 let prepared = w[0] == k && w[2] == r.view;
736
737 let mut is_bc = false;
742 let mut bword = b32(0);
743 let mut blen = b16(8);
744 let mut bpay = [b64(0); 8];
745 let mut bram = false;
746 let mut bbeats = b5(1);
747 let mut lwords = b3(2);
748 let mut bnext = r.st;
749 let vote = tag.resize::<64>() | (r.m.resize::<64>() << b64(32));
751 if r.st == b6(st::L_BCAST) {
752 is_bc = true;
754 bword = r.mb_prepare + (slot32 << b32(2));
755 blen = b16(16);
756 bpay[0] = k.resize::<64>() | (r.m.resize::<64>() << b64(32));
757 bpay[1] = r.view.resize();
758 lwords = b3(4);
759 bnext = b6(st::F_POLL_PREP);
760 }
761 if r.st == b6(st::F_BC_WC) || r.st == b6(st::F_BC_WM) || r.st == b6(st::S_BC_VALID) || r.st == b6(st::S_BC_COMMIT) {
762 is_bc = true;
763 bpay[0] = vote;
764 }
765 if r.st == b6(st::F_BC_WC) {
766 bword = r.mb_will_cert + (my_vote << b32(1));
767 bnext = b6(st::F_POLL_WC);
768 }
769 if r.st == b6(st::F_BC_WM) {
770 bword = r.mb_will_commit + (my_vote << b32(1));
771 bnext = b6(st::F_POLL_WM);
772 }
773 if r.st == b6(st::S_BC_VALID) {
774 bword = r.mb_certify_valid + (my_vote << b32(1));
776 bnext = b6(st::S_POLL_VALID);
777 }
778 if r.st == b6(st::S_BC_COMMIT) {
779 bword = r.mb_commit + (my_vote << b32(1));
780 bnext = b6(st::S_POLL_COMMIT);
781 }
782 if r.st == b6(st::S_BC_SIG) {
783 is_bc = true;
785 bword = r.mb_certify + ((my_vote * sb32) << b32(4));
786 blen = (sb32 << b32(6)).resize();
787 bram = true;
788 bbeats = b5(SB as u128);
789 lwords = b3(0);
790 bnext = b6(st::S_BC_VALID);
791 }
792 let vtag = vote_tag(r.view, b32(0xff_ffff));
793 if r.st == b6(st::V_BC_VC) {
794 is_bc = true;
796 bword = r.mb_vc + (id32 << b32(2));
797 blen = b16(16);
798 let slot_phase = slot32 | (r.voted_phase.resize::<32>() << b32(16));
799 bpay[0] = r.view.resize::<64>() | (slot_phase.resize::<64>() << b64(32));
800 bpay[1] = r.voted_k.resize::<64>() | (r.voted_m.resize::<64>() << b64(32));
801 lwords = b3(4);
802 bnext = b6(st::V_BC_VCV);
803 }
804 if r.st == b6(st::V_BC_VCV) {
805 is_bc = true;
807 bword = r.mb_vc_valid + id32;
808 blen = b16(4);
809 bpay[0] = vtag.resize();
810 lwords = b3(1);
811 bnext = b6(st::V_POLL_VCV);
812 }
813 if is_bc {
814 let no_peers = peers == b5(0);
815 o.bcast = BroadcastReq {
816 start: !r.issued && !r.bc_done && !no_peers,
817 qbase: r.qbase,
818 n: peers,
819 word: bword,
820 len: blen,
821 payload: bpay,
822 beats: bbeats,
823 from_ram: bram,
824 };
825 if !r.issued && !r.bc_done && !no_peers && !i.bcast.busy {
826 s.issued = true;
827 }
828 if (r.issued && i.bcast.done) || (no_peers && !r.bc_done) {
829 s.issued = false;
830 s.bc_done = true;
831 }
832 if r.bc_done {
833 let mut vals = [b32(0); 4];
834 for j in 0..4 {
835 let lane = bpay[j >> 1];
836 vals[j] = if (j & 1) == 1 { (lane >> b64(32)).resize() } else { lane.resize() };
837 }
838 let finish = lwords == b3(0) || (r.wissued && i.write.done);
839 o.write = WriteReq { start: lwords != b3(0) && !r.wissued, base: base, word: bword, values: vals, count: lwords };
840 if lwords != b3(0) && !r.wissued && !i.write.busy {
841 s.wissued = true;
842 }
843 if finish {
844 s.wissued = false;
845 s.bc_done = false;
846 s.local_wait = b32(0);
847 s.st = bnext;
848 if r.st == b6(st::L_BCAST) {
849 s.sub = b2(sub::FAST);
850 }
851 if r.st == b6(st::F_BC_WC) {
853 s.voted_k = k;
854 s.voted_m = r.m;
855 if r.voted_phase == b2(0) {
856 s.voted_phase = b2(1);
857 }
858 }
859 if r.st == b6(st::F_BC_WM) || r.st == b6(st::S_BC_COMMIT) {
860 s.voted_k = k;
861 s.voted_m = r.m;
862 s.voted_phase = b2(2);
863 }
864 }
865 }
866 }
867
868 if r.st == b6(st::F_WAIT_PREP) && got {
870 if prepared {
871 s.m = w[1];
872 s.local_wait = b32(0);
873 s.st = b6(st::F_BC_WC);
874 } else {
875 s.local_wait = r.local_wait + b32(1);
876 s.st = if timed_out { b6(st::S_INIT) } else { b6(st::F_POLL_PREP) };
877 }
878 }
879 let votes = count_votes(w, r.n, tag, r.m);
880 if r.st == b6(st::F_WAIT_WC) && got {
881 if votes >= r.quorum {
882 s.st = b6(st::F_BC_WM);
883 } else {
884 s.local_wait = r.local_wait + b32(1);
885 s.st = if timed_out { b6(st::S_INIT) } else { b6(st::F_POLL_WC) };
886 }
887 }
888 if r.st == b6(st::F_WAIT_WM) && got {
889 if votes >= r.quorum {
890 s.st = b6(st::DECIDE);
891 } else {
892 s.local_wait = r.local_wait + b32(1);
893 s.st = if timed_out { b6(st::S_INIT) } else { b6(st::F_POLL_WM) };
894 }
895 }
896
897 if r.st == b6(st::DECIDE) {
899 let mut d = [b64(0); 4];
900 d[0] = r.m.resize::<64>() | (k.resize::<64>() << b64(32));
901 o.output = Axis256 { valid: !r.out_sent, data: d, last: true };
902 o.remote = Axis256 { valid: !r.rem_sent, data: d, last: true };
903 let out_ok = r.out_sent || i.output_ready;
904 let rem_ok = r.rem_sent || i.remote_ready;
905 s.out_sent = out_ok;
906 s.rem_sent = rem_ok;
907 if out_ok && rem_ok {
908 s.out_sent = false;
909 s.rem_sent = false;
910 s.seq = r.seq + b32(1);
911 s.slot = if r.slot + b4(1) == b4(G as u128) { b4(0) } else { r.slot + b4(1) };
912 let took = r.status.cycles - r.slot_start;
913 s.status.decided = r.status.decided + b32(1);
914 if r.slowed {
915 s.status.slow = r.status.slow + b32(1);
916 } else {
917 s.status.fast = r.status.fast + b32(1);
918 }
919 if r.status.decided == b32(0) {
920 s.status.first = r.status.cycles;
921 s.status.slot_min = took;
922 }
923 s.status.last = r.status.cycles;
924 if r.status.decided != b32(0) && took < r.status.slot_min {
925 s.status.slot_min = took;
926 }
927 if took > r.status.slot_max {
928 s.status.slot_max = took;
929 }
930 s.status.slot_sum = r.status.slot_sum + took.resize::<64>();
931 for g in 0..G {
934 if r.slot == b4(g as u128) && r.id == r.leader {
935 s.prop_valid[g] = false;
936 }
937 }
938 let lead = r.id == r.leader;
940 s.st = if lead { b6(st::L_INIT) } else { b6(st::F_INIT) };
941 s.sub = if lead { b2(sub::LEADER) } else { b2(sub::FAST) };
942 }
943 }
944
945 if r.st == b6(st::S_INIT) {
947 s.local_wait = b32(0);
948 s.slowed = true;
949 s.sub = b2(sub::SLOW);
950 s.good = b5(1);
951 s.share_beat = b5(0);
952 for p in 0..N {
953 s.checked[p] = false;
954 }
955 s.st = b6(st::S_POLL_PREP);
956 }
957 if r.st == b6(st::S_WAIT_PREP) && got {
958 if prepared {
959 s.m = w[1];
960 s.local_wait = b32(0);
961 s.st = b6(st::S_SIGN);
962 } else {
963 s.local_wait = r.local_wait + b32(1);
964 s.st = if timed_out { b6(st::V_INIT) } else { b6(st::S_POLL_PREP) };
965 }
966 }
967 let mut summary = [b64(0); 8];
972 summary[0] = b64(0x3242_5552) | (b64(1) << b64(32));
973 summary[1] = r.args.session;
974 summary[2] = r.view.resize::<64>() | (slot32.resize::<64>() << b64(32));
975 summary[3] = k.resize::<64>() | (r.m.resize::<64>() << b64(32));
976 if r.st == b6(st::S_SIGN) {
977 let mut beat = [b64(0); 8];
979 beat[0] = r.seq.resize();
980 for j in 0..6 {
981 beat[j + 1] = summary[j];
982 }
983 o.sign = Axis512 { valid: true, data: beat, keep: !b64(0), last: true };
984 if i.sign_ready {
985 s.st = b6(st::S_SIG_WAIT);
986 }
987 }
988 if r.st == b6(st::S_SIG_WAIT) {
989 o.sig_ready = true;
991 if i.sig.valid {
992 let extra = !i.sig.last && r.share_beat >= b5(SB as u128);
995 o.ram_we = !i.sig.last && !extra;
996 o.ram_addr = r.share_beat;
997 o.ram_data = i.sig.data;
998 if !i.sig.last && !extra {
999 s.share_beat = r.share_beat + b5(1);
1000 }
1001 if extra {
1002 s.share_beat = b5(0);
1003 fault = fault | b32(4);
1004 stop = true;
1005 }
1006 if i.sig.last {
1007 s.share_beat = b5(0);
1008 let length_ok = r.share_beat == b5(SB as u128);
1010 let tag_ok = i.sig.data[0] == r.seq.resize::<64>();
1011 if length_ok && tag_ok {
1012 s.st = b6(st::S_BC_SIG);
1013 } else {
1014 fault = fault | b32(4);
1015 stop = true;
1016 }
1017 }
1018 }
1019 }
1020 if r.st == b6(st::S_WAIT_VALID) && got {
1021 let mut found = false;
1024 let mut pick = b5(0);
1025 for p in 0..16 {
1026 let mut unchecked = false;
1027 for q in 0..N {
1028 if p == q {
1029 unchecked = !r.checked[q];
1030 }
1031 }
1032 let flag = w[2 * p] == tag && w[2 * p + 1] == r.m;
1033 if !found && b5(p as u128) < r.n && b5(p as u128) != r.id && flag && unchecked {
1034 found = true;
1035 pick = b5(p as u128);
1036 }
1037 }
1038 if found {
1039 s.peer = pick;
1040 s.vbeats = b2(0);
1041 s.reading = false;
1042 s.st = b6(st::S_VERIFY);
1043 } else if r.good >= r.quorum {
1044 s.st = b6(st::S_BC_COMMIT);
1045 } else {
1046 s.local_wait = r.local_wait + b32(1);
1047 s.st = if timed_out { b6(st::V_INIT) } else { b6(st::S_POLL_VALID) };
1048 }
1049 }
1050 if r.st == b6(st::S_VERIFY) {
1051 let mut hdr = [b64(0); 8];
1053 hdr[0] = r.peer.resize::<64>() | (r.peer.resize::<64>() << b64(32));
1054 let beat = if r.vbeats == b2(0) { hdr } else { summary };
1055 o.verify = Axis512 { valid: true, data: beat, keep: !b64(0), last: false };
1056 if i.verify_ready {
1057 s.vbeats = r.vbeats + b2(1);
1058 if r.vbeats == b2(1) {
1059 s.st = b6(st::S_VER_SHARE);
1060 }
1061 }
1062 }
1063 if r.st == b6(st::S_VER_SHARE) {
1064 let word = r.mb_certify + (((slot_n + r.peer.resize::<32>()) * sb32) << b32(4));
1066 o.share = ShareReq { start: !r.reading, base: base, word: word, beats: b5(SB as u128) };
1067 if !r.reading && !i.share.busy {
1068 s.reading = true;
1069 }
1070 o.verify = i.share.out;
1071 o.share_ready = r.reading && i.verify_ready;
1072 if r.reading && i.share.out.valid && i.verify_ready && i.share.out.last {
1073 s.reading = false;
1074 s.st = b6(st::S_VERDICT);
1075 }
1076 }
1077 if r.st == b6(st::S_VERDICT) {
1078 o.verdict_ready = true;
1079 if i.verdict.valid {
1080 let slot_ok = ((i.verdict.data >> b64(8)) & b64(0xf)) == (r.peer.resize::<64>() & b64(0xf));
1082 let tag_ok = (i.verdict.data >> b64(32)) == r.peer.resize::<64>();
1083 if !(slot_ok && tag_ok) {
1084 fault = fault | b32(8);
1085 }
1086 let ok = slot_ok && tag_ok && (i.verdict.data & b64(0xff)) == b64(0x80);
1087 for q in 0..N {
1088 if r.peer == b5(q as u128) {
1089 s.checked[q] = true;
1090 }
1091 }
1092 if ok {
1093 s.good = r.good + b5(1);
1094 s.status.verified = r.status.verified + b32(1);
1095 } else {
1096 s.status.rejected = r.status.rejected + b32(1);
1097 }
1098 s.st = b6(st::S_POLL_VALID);
1099 }
1100 }
1101 if r.st == b6(st::S_WAIT_COMMIT) && got {
1102 if votes >= r.quorum {
1103 s.st = b6(st::DECIDE);
1104 } else {
1105 s.local_wait = r.local_wait + b32(1);
1106 s.st = if timed_out { b6(st::V_INIT) } else { b6(st::S_POLL_COMMIT) };
1107 }
1108 }
1109
1110 if r.st == b6(st::V_INIT) {
1112 s.view = r.view + b32(1);
1113 let mut l = r.leader + b5(1);
1115 if l == r.n {
1116 l = b5(0);
1117 }
1118 s.leader = l;
1119 s.status.views = r.status.views + b32(1);
1120 s.sub = b2(sub::VIEW);
1121 s.local_wait = b32(0);
1122 s.st = b6(st::V_BC_VC);
1123 }
1124 if r.st == b6(st::V_WAIT_VCV) && got {
1125 if count_flags(w, r.n, vtag) >= r.quorum {
1126 s.rec = b5(0);
1127 for q in 0..N {
1128 s.rec_ok[q] = false;
1129 }
1130 s.st = b6(st::V_POLL_REC);
1131 } else {
1132 s.local_wait = r.local_wait + b32(1);
1133 s.st = if timed_out { b6(st::V_INIT) } else { b6(st::V_POLL_VCV) };
1135 }
1136 }
1137 if r.st == b6(st::V_WAIT_REC) && got {
1138 let phase = (w[1] >> b32(16)) & b32(3);
1140 let ok = w[0] == r.view && (w[1] & b32(0xffff)) == slot32 && phase != b32(0) && w[2] == k;
1141 for q in 0..N {
1142 if r.rec == b5(q as u128) {
1143 s.rec_k[q] = w[2];
1144 s.rec_m[q] = w[3];
1145 s.rec_ok[q] = ok;
1146 }
1147 }
1148 s.rec = r.rec + b5(1);
1149 s.st = if r.rec + b5(1) == r.n { b6(st::V_CHOOSE) } else { b6(st::V_POLL_REC) };
1150 }
1151 if r.st == b6(st::V_CHOOSE) {
1152 let (found, m) = choose::<N>(r.rec_m, r.rec_ok, r.f);
1154 s.nv_k = if found { k } else { b32(0) };
1155 s.nv_m = m;
1156 s.st = b6(st::V_INSTALL);
1157 }
1158 if r.st == b6(st::V_INSTALL) {
1159 let install = r.nv_k != b32(0);
1162 let mut vals = [b32(0); 4];
1163 vals[0] = r.nv_k;
1164 vals[1] = r.nv_m;
1165 vals[2] = r.view;
1166 o.write = WriteReq { start: install && !r.wissued, base: base, word: r.mb_prepare + (slot32 << b32(2)), values: vals, count: b3(4) };
1167 if install && !r.wissued && !i.write.busy {
1168 s.wissued = true;
1169 }
1170 if !install || (r.wissued && i.write.done) {
1171 s.wissued = false;
1172 let lead = r.id == r.leader;
1173 s.local_wait = b32(0);
1174 if lead && !install {
1177 s.st = b6(st::L_INIT);
1178 s.sub = b2(sub::LEADER);
1179 } else {
1180 s.st = b6(st::F_POLL_PREP);
1182 s.sub = b2(sub::FAST);
1183 }
1184 }
1185 }
1186
1187 s.status.fault = fault;
1188 if stop && running {
1189 s.st = b6(st::IDLE);
1190 s.status.finished = true;
1191 }
1192 s.status.shape = b32(N as u128) | (b32(G as u128) << b32(8)) | (b32(SB as u128) << b32(24));
1193 s.status.state = r.sub.resize::<32>() | (r.st.resize::<32>() << b32(8)) | (r.view << b32(16));
1194 (o, s)
1195}