1use rhdl::prelude::*;
8use rhdl_fpga::core::dff::DFF;
9
10use crate::protocol::{CoreResult, Words512, idle_result};
11
12#[derive(Copy, Clone, Debug, PartialEq, Digital)]
14pub struct SignCompletion {
15 pub valid: bool,
17 pub tag: b16,
19 pub signature: Words512,
21}
22
23#[derive(Copy, Clone, Debug, PartialEq, Digital)]
25pub struct VerifyCompletion {
26 pub valid: bool,
28 pub tag: b16,
30 pub ok: bool,
32 pub error: b8,
34}
35
36#[derive(Copy, Clone, Debug, PartialEq, Digital)]
38pub struct ResultArbiterIn {
39 pub sign: SignCompletion,
41 pub verify: VerifyCompletion,
43 pub sign_internal_error: bool,
45 pub verify_internal_error: bool,
47}
48
49#[derive(Copy, Clone, Debug, PartialEq, Digital)]
51pub struct ResultArbiterOut {
52 pub verify_ready: bool,
54 pub result: CoreResult,
56 pub internal_error: bool,
58}
59
60#[derive(Copy, Clone, Debug, PartialEq, Digital)]
61#[doc(hidden)]
62pub struct ResultArbiterRegs {
63 queue: [VerifyCompletion; 64],
64 read: b6,
65 write: b6,
66 count: b7,
67 result: CoreResult,
68 internal_error: bool,
69}
70
71fn empty_verify() -> VerifyCompletion {
72 VerifyCompletion {
73 valid: false,
74 tag: b16(0),
75 ok: false,
76 error: b8(0),
77 }
78}
79
80fn reset_regs() -> ResultArbiterRegs {
81 ResultArbiterRegs {
82 queue: [empty_verify(); 64],
83 read: b6(0),
84 write: b6(0),
85 count: b7(0),
86 result: idle_result(),
87 internal_error: false,
88 }
89}
90
91#[derive(Clone, Debug, Synchronous, SynchronousDQ)]
93pub struct ResultArbiter {
94 regs: DFF<ResultArbiterRegs>,
95}
96
97impl Default for ResultArbiter {
98 fn default() -> Self {
99 Self {
100 regs: DFF::new(reset_regs()),
101 }
102 }
103}
104
105impl SynchronousIO for ResultArbiter {
106 type I = ResultArbiterIn;
107 type O = ResultArbiterOut;
108 type Kernel = result_arbiter_kernel;
109}
110
111#[kernel]
113pub fn result_arbiter_kernel(
114 _cr: ClockReset,
115 i: ResultArbiterIn,
116 q: ResultArbiterQ,
117) -> (ResultArbiterOut, ResultArbiterD) {
118 let r = q.regs;
119 let mut n = r;
120 n.result.valid = false;
121
122 let drain_verify = !i.sign.valid && r.count != b7(0);
123 let direct_verify = !i.sign.valid && r.count == b7(0) && i.verify.valid;
124 let enqueue_verify = i.verify.valid && !direct_verify;
125
126 if i.sign.valid {
127 n.result = CoreResult {
128 valid: true,
129 tag: i.sign.tag,
130 signature: i.sign.signature,
131 is_verify: false,
132 verify_ok: false,
133 error: b8(0),
134 };
135 } else if drain_verify {
136 let completion = r.queue[r.read];
137 n.result = CoreResult {
138 valid: true,
139 tag: completion.tag,
140 signature: Words512 { words: [b64(0); 8] },
141 is_verify: true,
142 verify_ok: completion.ok,
143 error: completion.error,
144 };
145 n.read = r.read + b6(1);
146 } else if direct_verify {
147 n.result = CoreResult {
148 valid: true,
149 tag: i.verify.tag,
150 signature: Words512 { words: [b64(0); 8] },
151 is_verify: true,
152 verify_ok: i.verify.ok,
153 error: i.verify.error,
154 };
155 }
156
157 if enqueue_verify {
158 if r.count != b7(64) || drain_verify {
159 n.queue[r.write] = i.verify;
160 n.write = r.write + b6(1);
161 } else {
162 n.internal_error = true;
163 }
164 }
165 if enqueue_verify && !drain_verify && r.count != b7(64) {
166 n.count = r.count + b7(1);
167 } else if !enqueue_verify && drain_verify {
168 n.count = r.count - b7(1);
169 }
170
171 if i.sign_internal_error || i.verify_internal_error {
172 n.internal_error = true;
173 }
174 let output = ResultArbiterOut {
175 verify_ready: r.count != b7(64) || drain_verify,
176 result: r.result,
177 internal_error: r.internal_error,
178 };
179 (output, ResultArbiterD { regs: n })
180}
181
182#[cfg(test)]
183mod tests {
184 use super::*;
185
186 fn idle() -> ResultArbiterIn {
187 ResultArbiterIn {
188 sign: SignCompletion {
189 valid: false,
190 tag: b16(0),
191 signature: Words512::zero(),
192 },
193 verify: empty_verify(),
194 sign_internal_error: false,
195 verify_internal_error: false,
196 }
197 }
198
199 #[test]
200 fn simultaneous_verification_is_retained_behind_signing() {
201 let mut both = idle();
202 both.sign.valid = true;
203 both.sign.tag = b16(0x51);
204 both.sign.signature.words[0] = b64(0x5151);
205 both.verify = VerifyCompletion {
206 valid: true,
207 tag: b16(0x71),
208 ok: true,
209 error: b8(0),
210 };
211 let results: Vec<_> = ResultArbiter::default()
212 .run(
213 [idle(), both, idle(), idle()]
214 .into_iter()
215 .with_reset(1)
216 .clock_pos_edge(100),
217 )
218 .synchronous_sample()
219 .map(|sample| sample.output.result)
220 .filter(|result| result.valid)
221 .collect();
222 assert_eq!(results.len(), 2);
223 assert_eq!(results[0].tag, b16(0x51));
224 assert!(!results[0].is_verify);
225 assert_eq!(results[1].tag, b16(0x71));
226 assert!(results[1].is_verify);
227 assert!(results[1].verify_ok);
228 }
229}