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