use anyhow::Result;
use clap::Args;
use serde_annotate::Annotate;
use std::path::{Path, PathBuf};
use std::time::Duration;
use crate::app::{StagedProgressBar, TransportWrapper};
use crate::transport::common::fpga::{ClearBitstream, FpgaProgram};
#[derive(Debug, Args)]
pub struct LoadBitstream {
#[arg(long)]
pub clear_bitstream: bool,
#[arg(long)]
pub bitstream: Option<PathBuf>,
#[arg(long, value_parser = humantime::parse_duration, default_value = "50ms")]
pub rom_reset_pulse: Duration,
#[arg(long, value_parser = humantime::parse_duration, default_value = "2s")]
pub rom_timeout: Duration,
}
impl LoadBitstream {
pub fn init(&self, transport: &TransportWrapper) -> Result<Option<Box<dyn Annotate>>> {
if self.clear_bitstream {
log::info!("Clearing bitstream.");
transport.dispatch(&ClearBitstream)?;
}
if let Some(bitstream) = &self.bitstream {
self.load(transport, bitstream)
} else {
Ok(None)
}
}
pub fn load(
&self,
transport: &TransportWrapper,
file: &Path,
) -> Result<Option<Box<dyn Annotate>>> {
log::info!("Loading bitstream: {:?}", file);
let payload = std::fs::read(file)?;
let progress = StagedProgressBar::new();
let operation = FpgaProgram {
bitstream: payload,
rom_reset_pulse: self.rom_reset_pulse,
rom_timeout: self.rom_timeout,
progress: Box::new(progress),
};
if operation.should_skip(transport)? {
return Ok(None);
}
transport.dispatch(&operation)
}
}