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::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 #[arg(long)]
34 pub force: bool,
35}
36
37impl LoadBitstream {
38 pub fn init(&self, transport: &TransportWrapper) -> Result<()> {
39 if self.clear_bitstream {
41 log::info!("Clearing bitstream.");
42 transport.fpga_ops()?.clear_bitstream()?;
43 }
44 if let Some(bitstream) = &self.bitstream {
46 self.load(transport, bitstream)?;
47 }
48
49 Ok(())
50 }
51
52 pub fn load(&self, transport: &TransportWrapper, file: &Path) -> Result<()> {
53 log::info!("Loading bitstream: {:?}", file);
54 let payload = std::fs::read(file)?;
55 let progress = StagedProgressBar::new();
56 let operation = FpgaProgram {
57 bitstream: payload,
58 rom_reset_pulse: self.rom_reset_pulse,
59 rom_timeout: self.rom_timeout,
60 progress: Box::new(progress),
61 };
62
63 if !self.force && operation.should_skip(transport)? {
64 return Ok(());
65 }
66
67 transport
68 .fpga_ops()?
69 .load_bitstream(&operation.bitstream, &*operation.progress)
70 }
71}