1use rhdl::prelude::*;
25
26pub use crate::ports::{
27 AxiLiteIn, AxiLiteOut, AxiRead, AxiReadResp, AxiWrite, AxiWriteResp, Axis64, Axis256, Axis512, CryptoIn, CryptoOut, CryptoScheme,
28};
29
30#[derive(Clone, Copy, Debug, PartialEq, Digital, Default)]
32pub struct ReplicaIn {
33 pub ctl: AxiLiteIn,
35 pub input: Axis64,
37 pub output_ready: bool,
39 pub remote_ready: bool,
41 pub tx_meta_ready: bool,
43 pub tx_data_ready: bool,
45 pub tx_status: Axis512,
47 pub net_r: AxiReadResp,
49 pub net_w: AxiWriteResp,
51 pub msg_r: AxiReadResp,
53 pub crypto_resp: CryptoOut,
56}
57
58#[derive(Clone, Copy, Debug, PartialEq, Digital, Default)]
60pub struct ReplicaOut {
61 pub ctl: AxiLiteOut,
63 pub input_ready: bool,
65 pub output: Axis256,
67 pub remote: Axis256,
69 pub tx_meta: Axis256,
71 pub tx_data: Axis512,
73 pub tx_status_ready: bool,
75 pub net_r: AxiRead,
77 pub net_w: AxiWrite,
79 pub msg_r: AxiRead,
81 pub crypto_req: CryptoIn,
84}
85
86#[macro_export]
89macro_rules! define_replica {
90 ($(#[$m:meta])* $name:ident, $crypto:ty, $sb:expr) => {
91 $crate::define_replica!(@impl $(#[$m])* $name, $crypto, $sb, false);
92 };
93 ($(#[$m:meta])* $name:ident, external $sb:expr) => {
96 $crate::define_replica!(@impl $(#[$m])* $name, $crate::crypto::external::External<{ $sb }>, $sb, true);
97 };
98 (@impl $(#[$m:meta])* $name:ident, $crypto:ty, $sb:expr, $ext:expr) => {
99 $crate::replica::paste! {
100 #[derive(Clone, Debug, Synchronous, SynchronousDQ)]
102 pub struct $name<const N: usize, const G: usize> {
103 control: $crate::control::Control,
104 protocol: rhdl_fpga::core::dff::DFF<$crate::protocol::ProtocolState<N, G>>,
105 fetch: $crate::fetch::Fetcher,
106 share: $crate::share::ShareReader,
107 bcast: $crate::broadcast::Broadcaster,
108 write: $crate::writer::Writer,
109 share_ram: rhdl_fpga::core::ram::synchronous::SyncBRAM<[b64; 8], 5>,
110 crypto: $crypto,
111 }
112
113 impl<const N: usize, const G: usize> $name<N, G> {
114 pub fn new() -> Self {
116 assert_eq!($sb, <$crypto as $crate::ports::CryptoScheme>::SHARE_BEATS, "SB must be the scheme's SHARE_BEATS");
117 assert!($sb <= 31 && (1..=16).contains(&N) && (1..=8).contains(&G));
118 Self {
119 control: $crate::control::Control::default(),
120 protocol: rhdl_fpga::core::dff::DFF::new($crate::protocol::ProtocolState::<N, G>::idle()),
121 fetch: $crate::fetch::Fetcher::default(),
122 share: $crate::share::ShareReader::default(),
123 bcast: $crate::broadcast::Broadcaster::default(),
124 write: $crate::writer::Writer::default(),
125 share_ram: rhdl_fpga::core::ram::synchronous::SyncBRAM::new(std::iter::empty()),
126 crypto: <$crypto>::default(),
127 }
128 }
129 }
130
131 impl<const N: usize, const G: usize> Default for $name<N, G> {
132 fn default() -> Self {
133 Self::new()
134 }
135 }
136
137 impl<const N: usize, const G: usize> SynchronousIO for $name<N, G> {
138 type I = $crate::replica::ReplicaIn;
139 type O = $crate::replica::ReplicaOut;
140 type Kernel = [<$name:snake _kernel>]<N, G>;
141 }
142
143 #[kernel]
145 pub fn [<$name:snake _kernel>]<const N: usize, const G: usize>(
146 _cr: ClockReset,
147 i: $crate::replica::ReplicaIn,
148 q: [<$name Q>]<N, G>,
149 ) -> ($crate::replica::ReplicaOut, [<$name D>]<N, G>) {
150 let mut d = [<$name D>]::<N, G>::dont_care();
151 let ctl = q.control;
152 let cr = if $ext { i.crypto_resp } else { q.crypto };
154
155 let (p, next) = $crate::protocol::protocol_kernel::<N, G, $sb>(
157 $crate::protocol::ProtocolIn {
158 start: ctl.start,
159 args: ctl.args,
160 setup_done: cr.ready,
161 fetch: q.fetch,
162 bcast: q.bcast,
163 write: q.write,
164 share: q.share,
165 input: i.input,
166 output_ready: i.output_ready,
167 remote_ready: i.remote_ready,
168 sign_ready: cr.sign_ready,
169 sig: cr.sig,
170 verify_ready: cr.verify_ready,
171 verdict: cr.verdict,
172 },
173 q.protocol,
174 );
175 d.protocol = next;
176 d.control = $crate::control::ControlIn { axi: i.ctl, status: p.status };
177
178 let share_active = q.share.busy;
180 d.fetch = $crate::fetch::FetchIn {
181 req: p.fetch,
182 axi: $crate::ports::AxiReadResp {
183 ar_ready: i.net_r.ar_ready && !share_active,
184 r_valid: i.net_r.r_valid && !share_active,
185 r_data: i.net_r.r_data,
186 r_last: i.net_r.r_last,
187 },
188 };
189 d.share = $crate::share::ShareIn {
190 req: p.share,
191 axi: $crate::ports::AxiReadResp {
192 ar_ready: i.net_r.ar_ready && share_active,
193 r_valid: i.net_r.r_valid && share_active,
194 r_data: i.net_r.r_data,
195 r_last: i.net_r.r_last,
196 },
197 out_ready: p.share_ready,
198 };
199 let net_r = if share_active { q.share.axi } else { q.fetch.axi };
200
201 d.bcast = $crate::broadcast::BroadcastIn { req: p.bcast, meta_ready: i.tx_meta_ready, data_ready: i.tx_data_ready, ram_data: q.share_ram };
203 d.share_ram.read_addr = q.bcast.ram_addr;
204 d.share_ram.write.addr = p.ram_addr;
205 d.share_ram.write.value = p.ram_data;
206 d.share_ram.write.enable = p.ram_we;
207 d.write = $crate::writer::WriteIn { req: p.write, axi: i.net_w };
208
209 let creq = $crate::ports::CryptoIn {
211 setup: ctl.start,
212 n: ctl.args.node_num.resize(),
213 id: ctl.args.id.resize(),
214 sk: ctl.args.sk,
215 keys_base: ctl.args.message_ptr,
216 msg: i.msg_r,
217 sign: p.sign,
218 sig_ready: p.sig_ready,
219 verify: p.verify,
220 verdict_ready: p.verdict_ready,
221 announce_ready: true,
222 cfg: ctl.cfg,
223 cert: $crate::ports::Axis512 { valid: false, data: [b64(0); 8], keep: b64(0), last: false },
224 };
225 d.crypto = creq;
226
227 let o = $crate::replica::ReplicaOut {
228 ctl: ctl.axi,
229 input_ready: p.input_ready,
230 output: p.output,
231 remote: p.remote,
232 tx_meta: q.bcast.meta,
233 tx_data: q.bcast.data,
234 tx_status_ready: true,
235 net_r: net_r,
236 net_w: q.write.axi,
237 msg_r: cr.msg,
238 crypto_req: creq,
239 };
240 (o, d)
241 }
242 }
243 };
244}
245
246#[doc(hidden)]
247pub use paste::paste;
248
249#[cfg(feature = "ed25519")]
250define_replica!(
251 RhdlUbftEd25519,
253 crate::crypto::ed25519::Ed25519Crypto<{ crate::build_config::BUILD_VERIFY_MACHINES }>,
254 1
255);
256
257define_replica!(
258 RhdlUbftExternal1,
262 external 1
263);