1use core::marker::PhantomData;
8use thiserror::Error;
9
10pub mod align;
11pub use align::Aligned;
12
13#[cfg(feature = "f1")]
14pub mod f1;
15#[cfg(feature = "f1")]
16pub use f1::F1;
17
18pub mod null;
19pub use null::Null;
20
21#[derive(Debug, Error)]
22pub enum Error {
23 #[error("FPGA drivers require running as root.")]
24 SudoRequired,
25}
26
27pub type Result<T> = core::result::Result<T, Error>;
28
29pub trait Flush {
31 fn flush(&mut self);
33}
34
35pub trait Write<V>: Flush {
37 fn write(&mut self, index: usize, value: &V);
39}
40
41pub trait ReadWrite<V>: Write<V> {
43 fn read(&self, index: usize) -> V;
45}
46
47pub trait Backoff<FPGA> {
49 fn backoff(fpga: &mut FPGA, offset: usize);
50}
51
52pub struct Stream<'a, P, FPGA: Write<P>, B = null::Backoff> {
56 fpga: &'a mut FPGA,
57 offset: usize,
58 __: PhantomData<(B, P)>,
59}
60
61pub trait Streamable<'a, P, B: Backoff<Self> = null::Backoff>: Sized + Write<P> {
63 fn stream(&'a mut self, offset: usize) -> Stream<'a, P, Self, B>;
65}
66
67impl<'a, P, FPGA: Write<P>, B: Backoff<FPGA>> Streamable<'a, P, B> for FPGA {
68 fn stream(&'a mut self, offset: usize) -> Stream<'a, P, FPGA, B> {
69 Stream {
70 fpga: self,
71 offset,
72 __: PhantomData,
73 }
74 }
75}
76
77impl<'a, P, FPGA: Flush + Write<P>, B> Flush for Stream<'a, P, FPGA, B> {
78 fn flush(&mut self) {
79 self.fpga.flush()
80 }
81}
82
83impl<'a, P, FPGA: Write<P>, B> Stream<'a, P, FPGA, B> {
84 pub fn fpga(&mut self) -> &mut FPGA {
85 self.fpga
86 }
87
88 #[inline(always)]
89 pub fn offset(&self) -> usize {
90 self.offset
91 }
92}
93
94impl<'a, P, FPGA: Write<P>, B: Backoff<FPGA>> Stream<'a, P, FPGA, B> {
95 #[inline(always)]
96 pub fn write(&mut self, packet: &P) {
97 self.fpga.write(self.offset, packet);
98 self.offset += 1;
99 B::backoff(self.fpga, self.offset);
100 }
101}