Skip to main content

IoTransferWindow

Struct IoTransferWindow 

Source
pub struct IoTransferWindow<'session, 'board> { /* private fields */ }
Expand description

A rolling VeriComm pipeline that keeps up to capacity transfers in flight.

All transfers in one window have the same word length chosen up front. Submit frames with Self::submit and retire them in order with Self::receive_into. Dropping the window cancels any remaining transfers and recycles their buffers back into the parent IoSession.

Implementations§

Source§

impl<'session, 'board> IoTransferWindow<'session, 'board>

Source

pub fn words(&self) -> usize

Source

pub fn capacity(&self) -> usize

Source

pub fn pending(&self) -> usize

Source

pub fn available(&self) -> usize

Source

pub fn is_empty(&self) -> bool

Source

pub fn is_full(&self) -> bool

Source

pub fn submit(&mut self, tx: &[u16]) -> Result<()>

Queues one transfer into the rolling window.

Examples found in repository?
examples/bench_transfer.rs (line 185)
147fn run_device_bench(options: &Options) -> Result<(), Box<dyn Error>> {
148    let mut board = Board::open_with_transport(options.transport)?;
149    let max_cycles_per_transfer = usize::from(board.config().fifo_size_words()) / WORDS_PER_CYCLE;
150    let mut io = board.configure_io(&IoConfig {
151        clock_high_delay: options.clock_high_delay,
152        clock_low_delay: options.clock_low_delay,
153        ..IoConfig::default()
154    })?;
155
156    if options.window == 0 {
157        return Err("window must be at least 1".into());
158    }
159
160    let template = vec![0x1234u16; options.words];
161    let mut rx = vec![0u16; options.words];
162    let mut outputs = vec![vec![0u16; options.words]; options.window];
163    let mut stage_profile = TransferStageProfile::default();
164
165    let started = Instant::now();
166    if options.window == 1 {
167        if options.profile_stages {
168            for _ in 0..options.iterations {
169                let profile = io.transfer_profiled_into(&template, &mut rx)?;
170                stage_profile.merge(&profile);
171            }
172        } else {
173            for _ in 0..options.iterations {
174                io.transfer(&template, &mut rx)?;
175            }
176        }
177    } else {
178        let mut window = io.transfer_window(options.words, options.window)?;
179        let initial = options.iterations.min(options.window);
180        for _ in 0..initial {
181            if options.profile_stages {
182                let profile = window.submit_profiled(&template)?;
183                stage_profile.merge(&profile);
184            } else {
185                window.submit(&template)?;
186            }
187        }
188
189        let mut submitted = initial;
190        let mut completed = 0usize;
191        while completed < options.iterations {
192            let output = outputs[completed % options.window].as_mut_slice();
193            if options.profile_stages {
194                let profile = window.receive_into_profiled(output)?;
195                stage_profile.merge(&profile);
196            } else {
197                window.receive_into(output)?;
198            }
199            completed += 1;
200
201            if submitted < options.iterations {
202                if options.profile_stages {
203                    let profile = window.submit_profiled(&template)?;
204                    stage_profile.merge(&profile);
205                } else {
206                    window.submit(&template)?;
207                }
208                submitted += 1;
209            }
210        }
211    }
212    let elapsed = started.elapsed();
213    io.finish()?;
214
215    print_summary(
216        "device",
217        options.words,
218        options.iterations,
219        elapsed,
220        Some(max_cycles_per_transfer),
221    );
222    if options.profile_stages {
223        print_stage_profile(&stage_profile, elapsed);
224    }
225    Ok(())
226}
More examples
Hide additional examples
examples/stress_abort.rs (line 74)
12fn real_main() -> Result<(), Box<dyn Error>> {
13    let mut iterations = 10usize;
14    let mut words = 512usize;
15    let mut window = 4usize;
16    let mut clock_high = 4u16;
17    let mut clock_low = 4u16;
18    let mut settle_ms = 0u64;
19
20    let mut args = env::args().skip(1);
21    while let Some(flag) = args.next() {
22        match flag.as_str() {
23            "--iterations" => {
24                iterations = args
25                    .next()
26                    .ok_or("missing value for --iterations")?
27                    .parse()?
28            }
29            "--words" => words = args.next().ok_or("missing value for --words")?.parse()?,
30            "--window" => window = args.next().ok_or("missing value for --window")?.parse()?,
31            "--clock-high" => {
32                clock_high = args
33                    .next()
34                    .ok_or("missing value for --clock-high")?
35                    .parse()?
36            }
37            "--clock-low" => {
38                clock_low = args
39                    .next()
40                    .ok_or("missing value for --clock-low")?
41                    .parse()?
42            }
43            "--settle-ms" => {
44                settle_ms = args
45                    .next()
46                    .ok_or("missing value for --settle-ms")?
47                    .parse()?
48            }
49            other => return Err(format!("unknown flag `{other}`").into()),
50        }
51    }
52
53    let tx = vec![0x1234u16; words];
54
55    for iteration in 0..iterations {
56        println!("iter={iteration} phase=open");
57        let mut board = Board::open()?;
58        println!(
59            "iter={iteration} config programmed={} fifo_words={} version=0x{:04x}",
60            board.config().is_programmed(),
61            board.config().fifo_size_words(),
62            board.config().smims_version_raw()
63        );
64
65        let mut io = board.configure_io(&IoConfig {
66            clock_high_delay: clock_high,
67            clock_low_delay: clock_low,
68            ..IoConfig::default()
69        })?;
70
71        {
72            let mut rolling = io.transfer_window(words, window)?;
73            for submit_index in 0..window {
74                rolling.submit(&tx)?;
75                println!("iter={iteration} submit={submit_index}");
76            }
77            if settle_ms > 0 {
78                thread::sleep(Duration::from_millis(settle_ms));
79            }
80        }
81
82        io.finish()?;
83        board.close()?;
84
85        println!("iter={iteration} phase=reopen");
86        let reopened = Board::open()?;
87        println!(
88            "iter={iteration} reopened programmed={} fifo_words={} version=0x{:04x}",
89            reopened.config().is_programmed(),
90            reopened.config().fifo_size_words(),
91            reopened.config().smims_version_raw()
92        );
93        reopened.close()?;
94    }
95
96    Ok(())
97}
Source

pub fn submit_profiled(&mut self, tx: &[u16]) -> Result<TransferStageProfile>

Queues one transfer and returns a stage profile for that submission.

Examples found in repository?
examples/bench_transfer.rs (line 182)
147fn run_device_bench(options: &Options) -> Result<(), Box<dyn Error>> {
148    let mut board = Board::open_with_transport(options.transport)?;
149    let max_cycles_per_transfer = usize::from(board.config().fifo_size_words()) / WORDS_PER_CYCLE;
150    let mut io = board.configure_io(&IoConfig {
151        clock_high_delay: options.clock_high_delay,
152        clock_low_delay: options.clock_low_delay,
153        ..IoConfig::default()
154    })?;
155
156    if options.window == 0 {
157        return Err("window must be at least 1".into());
158    }
159
160    let template = vec![0x1234u16; options.words];
161    let mut rx = vec![0u16; options.words];
162    let mut outputs = vec![vec![0u16; options.words]; options.window];
163    let mut stage_profile = TransferStageProfile::default();
164
165    let started = Instant::now();
166    if options.window == 1 {
167        if options.profile_stages {
168            for _ in 0..options.iterations {
169                let profile = io.transfer_profiled_into(&template, &mut rx)?;
170                stage_profile.merge(&profile);
171            }
172        } else {
173            for _ in 0..options.iterations {
174                io.transfer(&template, &mut rx)?;
175            }
176        }
177    } else {
178        let mut window = io.transfer_window(options.words, options.window)?;
179        let initial = options.iterations.min(options.window);
180        for _ in 0..initial {
181            if options.profile_stages {
182                let profile = window.submit_profiled(&template)?;
183                stage_profile.merge(&profile);
184            } else {
185                window.submit(&template)?;
186            }
187        }
188
189        let mut submitted = initial;
190        let mut completed = 0usize;
191        while completed < options.iterations {
192            let output = outputs[completed % options.window].as_mut_slice();
193            if options.profile_stages {
194                let profile = window.receive_into_profiled(output)?;
195                stage_profile.merge(&profile);
196            } else {
197                window.receive_into(output)?;
198            }
199            completed += 1;
200
201            if submitted < options.iterations {
202                if options.profile_stages {
203                    let profile = window.submit_profiled(&template)?;
204                    stage_profile.merge(&profile);
205                } else {
206                    window.submit(&template)?;
207                }
208                submitted += 1;
209            }
210        }
211    }
212    let elapsed = started.elapsed();
213    io.finish()?;
214
215    print_summary(
216        "device",
217        options.words,
218        options.iterations,
219        elapsed,
220        Some(max_cycles_per_transfer),
221    );
222    if options.profile_stages {
223        print_stage_profile(&stage_profile, elapsed);
224    }
225    Ok(())
226}
Source

pub fn receive_into(&mut self, output: &mut [u16]) -> Result<()>

Retires the oldest in-flight transfer into output.

Examples found in repository?
examples/bench_transfer.rs (line 197)
147fn run_device_bench(options: &Options) -> Result<(), Box<dyn Error>> {
148    let mut board = Board::open_with_transport(options.transport)?;
149    let max_cycles_per_transfer = usize::from(board.config().fifo_size_words()) / WORDS_PER_CYCLE;
150    let mut io = board.configure_io(&IoConfig {
151        clock_high_delay: options.clock_high_delay,
152        clock_low_delay: options.clock_low_delay,
153        ..IoConfig::default()
154    })?;
155
156    if options.window == 0 {
157        return Err("window must be at least 1".into());
158    }
159
160    let template = vec![0x1234u16; options.words];
161    let mut rx = vec![0u16; options.words];
162    let mut outputs = vec![vec![0u16; options.words]; options.window];
163    let mut stage_profile = TransferStageProfile::default();
164
165    let started = Instant::now();
166    if options.window == 1 {
167        if options.profile_stages {
168            for _ in 0..options.iterations {
169                let profile = io.transfer_profiled_into(&template, &mut rx)?;
170                stage_profile.merge(&profile);
171            }
172        } else {
173            for _ in 0..options.iterations {
174                io.transfer(&template, &mut rx)?;
175            }
176        }
177    } else {
178        let mut window = io.transfer_window(options.words, options.window)?;
179        let initial = options.iterations.min(options.window);
180        for _ in 0..initial {
181            if options.profile_stages {
182                let profile = window.submit_profiled(&template)?;
183                stage_profile.merge(&profile);
184            } else {
185                window.submit(&template)?;
186            }
187        }
188
189        let mut submitted = initial;
190        let mut completed = 0usize;
191        while completed < options.iterations {
192            let output = outputs[completed % options.window].as_mut_slice();
193            if options.profile_stages {
194                let profile = window.receive_into_profiled(output)?;
195                stage_profile.merge(&profile);
196            } else {
197                window.receive_into(output)?;
198            }
199            completed += 1;
200
201            if submitted < options.iterations {
202                if options.profile_stages {
203                    let profile = window.submit_profiled(&template)?;
204                    stage_profile.merge(&profile);
205                } else {
206                    window.submit(&template)?;
207                }
208                submitted += 1;
209            }
210        }
211    }
212    let elapsed = started.elapsed();
213    io.finish()?;
214
215    print_summary(
216        "device",
217        options.words,
218        options.iterations,
219        elapsed,
220        Some(max_cycles_per_transfer),
221    );
222    if options.profile_stages {
223        print_stage_profile(&stage_profile, elapsed);
224    }
225    Ok(())
226}
Source

pub fn receive_into_profiled( &mut self, output: &mut [u16], ) -> Result<TransferStageProfile>

Retires the oldest in-flight transfer and returns its stage profile.

Examples found in repository?
examples/bench_transfer.rs (line 194)
147fn run_device_bench(options: &Options) -> Result<(), Box<dyn Error>> {
148    let mut board = Board::open_with_transport(options.transport)?;
149    let max_cycles_per_transfer = usize::from(board.config().fifo_size_words()) / WORDS_PER_CYCLE;
150    let mut io = board.configure_io(&IoConfig {
151        clock_high_delay: options.clock_high_delay,
152        clock_low_delay: options.clock_low_delay,
153        ..IoConfig::default()
154    })?;
155
156    if options.window == 0 {
157        return Err("window must be at least 1".into());
158    }
159
160    let template = vec![0x1234u16; options.words];
161    let mut rx = vec![0u16; options.words];
162    let mut outputs = vec![vec![0u16; options.words]; options.window];
163    let mut stage_profile = TransferStageProfile::default();
164
165    let started = Instant::now();
166    if options.window == 1 {
167        if options.profile_stages {
168            for _ in 0..options.iterations {
169                let profile = io.transfer_profiled_into(&template, &mut rx)?;
170                stage_profile.merge(&profile);
171            }
172        } else {
173            for _ in 0..options.iterations {
174                io.transfer(&template, &mut rx)?;
175            }
176        }
177    } else {
178        let mut window = io.transfer_window(options.words, options.window)?;
179        let initial = options.iterations.min(options.window);
180        for _ in 0..initial {
181            if options.profile_stages {
182                let profile = window.submit_profiled(&template)?;
183                stage_profile.merge(&profile);
184            } else {
185                window.submit(&template)?;
186            }
187        }
188
189        let mut submitted = initial;
190        let mut completed = 0usize;
191        while completed < options.iterations {
192            let output = outputs[completed % options.window].as_mut_slice();
193            if options.profile_stages {
194                let profile = window.receive_into_profiled(output)?;
195                stage_profile.merge(&profile);
196            } else {
197                window.receive_into(output)?;
198            }
199            completed += 1;
200
201            if submitted < options.iterations {
202                if options.profile_stages {
203                    let profile = window.submit_profiled(&template)?;
204                    stage_profile.merge(&profile);
205                } else {
206                    window.submit(&template)?;
207                }
208                submitted += 1;
209            }
210        }
211    }
212    let elapsed = started.elapsed();
213    io.finish()?;
214
215    print_summary(
216        "device",
217        options.words,
218        options.iterations,
219        elapsed,
220        Some(max_cycles_per_transfer),
221    );
222    if options.profile_stages {
223        print_stage_profile(&stage_profile, elapsed);
224    }
225    Ok(())
226}

Trait Implementations§

Source§

impl Drop for IoTransferWindow<'_, '_>

Source§

fn drop(&mut self)

Executes the destructor for this type. Read more

Auto Trait Implementations§

§

impl<'session, 'board> Freeze for IoTransferWindow<'session, 'board>

§

impl<'session, 'board> !RefUnwindSafe for IoTransferWindow<'session, 'board>

§

impl<'session, 'board> Send for IoTransferWindow<'session, 'board>

§

impl<'session, 'board> Sync for IoTransferWindow<'session, 'board>

§

impl<'session, 'board> Unpin for IoTransferWindow<'session, 'board>

§

impl<'session, 'board> UnsafeUnpin for IoTransferWindow<'session, 'board>

§

impl<'session, 'board> !UnwindSafe for IoTransferWindow<'session, 'board>

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.