opentitanlib/test_utils/
load_bitstream.rs1use anyhow::Result;
6use clap::Args;
7use std::path::{Path, PathBuf};
8use std::time::Duration;
9
10use crate::app::{StagedProgressBar, TransportWrapper};
11use crate::transport::common::fpga::{ClearBitstream, FpgaProgram};
12
13#[derive(Debug, Args)]
15pub struct LoadBitstream {
16 #[arg(long)]
18 pub clear_bitstream: bool,
19
20 #[arg(long)]
22 pub bitstream: Option<PathBuf>,
23
24 #[arg(long, value_parser = humantime::parse_duration, default_value = "50ms")]
26 pub rom_reset_pulse: Duration,
27
28 #[arg(long, value_parser = humantime::parse_duration, default_value = "2s")]
30 pub rom_timeout: Duration,
31}
32
33impl LoadBitstream {
34 pub fn init(
35 &self,
36 transport: &TransportWrapper,
37 ) -> Result<Option<Box<dyn erased_serde::Serialize>>> {
38 if self.clear_bitstream {
40 log::info!("Clearing bitstream.");
41 transport.dispatch(&ClearBitstream)?;
42 }
43 if let Some(bitstream) = &self.bitstream {
45 self.load(transport, bitstream)
46 } else {
47 Ok(None)
48 }
49 }
50
51 pub fn load(
52 &self,
53 transport: &TransportWrapper,
54 file: &Path,
55 ) -> Result<Option<Box<dyn erased_serde::Serialize>>> {
56 log::info!("Loading bitstream: {:?}", file);
57 let payload = std::fs::read(file)?;
58 let progress = StagedProgressBar::new();
59 let operation = FpgaProgram {
60 bitstream: payload,
61 rom_reset_pulse: self.rom_reset_pulse,
62 rom_timeout: self.rom_timeout,
63 progress: Box::new(progress),
64 };
65
66 if operation.should_skip(transport)? {
67 return Ok(None);
68 }
69 transport.dispatch(&operation)
70 }
71}