use crate::config;
use crate::error::FpgadError;
use crate::platforms::platform::Fpga;
use crate::softeners::xilinx_dfx_mgr;
use crate::system_io::{fs_read, fs_write};
use log::{error, trace};
use std::path::Path;
pub struct XilinxDfxMgrFPGA {
device_handle: String,
}
impl XilinxDfxMgrFPGA {
pub(crate) fn new(device_handle: &str) -> Self {
XilinxDfxMgrFPGA {
device_handle: device_handle.to_owned(),
}
}
}
impl Fpga for XilinxDfxMgrFPGA {
fn device_handle(&self) -> &str {
self.device_handle.as_str()
}
fn state(&self) -> Result<String, FpgadError> {
Ok(xilinx_dfx_mgr::list_package()?)
}
fn flags(&self) -> Result<u32, FpgadError> {
let flag_path = Path::new(config::FPGA_MANAGERS_DIR)
.join(self.device_handle.clone())
.join("flags");
let contents = fs_read(&flag_path)?;
let trimmed = contents.trim().trim_start_matches("0x");
u32::from_str_radix(trimmed, 16)
.map_err(|_| FpgadError::Flag("Parsing flags failed".into()))
}
fn set_flags(&self, flags: u32) -> Result<String, FpgadError> {
let flag_path = Path::new(config::FPGA_MANAGERS_DIR)
.join(self.device_handle.clone())
.join("flags");
trace!("Writing '0x{flags:X}' to '{flag_path:#?}'");
if let Err(e) = fs_write(&flag_path, false, format!("0x{flags:X}")) {
error!("Failed to read state.");
return Err(e);
}
match self.flags() {
Ok(returned_flags) if returned_flags == flags => Ok(format!(
"Flags set to '0x{:X}' for '{}'",
flags, self.device_handle
)),
Ok(returned_flags) => Err(FpgadError::Flag(format!(
"Setting '{}'s flags to '{}' failed. Resulting flag was '{}'",
self.device_handle, flags, returned_flags
))),
Err(e) => Err(FpgadError::Flag(format!(
"Failed to read '{}'s flags after setting to '{}': {}",
self.device_handle, flags, e
))),
}
}
fn load_firmware(&self, firmware_path: &Path, _: &Path) -> Result<String, FpgadError> {
Ok(xilinx_dfx_mgr::load_bitstream(firmware_path)?)
}
fn remove_firmware(&self, slot_handle: Option<&str>) -> Result<String, FpgadError> {
Ok(xilinx_dfx_mgr::remove(slot_handle)?)
}
}