use std::path::Path;
use std::sync::OnceLock;
use crate::error::FpgadError;
use crate::platforms::platform::{Fpga, OverlayHandler, Platform};
use crate::softeners::error::FpgadSoftenerError;
use fpgad_macros::platform;
use log::{info, trace};
use xilinx_dfx_mgr_fpga::XilinxDfxMgrFPGA;
use xilinx_dfx_mgr_helpers::run_dfx_mgr;
use xilinx_dfx_mgr_overlay_handler::XilinxDfxMgrOverlayHandler;
pub mod xilinx_dfx_mgr_fpga;
pub mod xilinx_dfx_mgr_helpers;
pub mod xilinx_dfx_mgr_overlay_handler;
#[platform(compat_string = "xlnx,zynqmp-pcap-fpga,versal-fpga,zynq-devcfg-1.0,dfx-mgr,softener")]
pub struct XilinxDfxMgrPlatform {
fpga: OnceLock<XilinxDfxMgrFPGA>,
overlay_handler: OnceLock<XilinxDfxMgrOverlayHandler>,
}
impl Default for XilinxDfxMgrPlatform {
fn default() -> Self {
Self::new()
}
}
impl XilinxDfxMgrPlatform {
pub fn new() -> Self {
trace!("creating new XilinxDfxMgrPlatform");
XilinxDfxMgrPlatform {
fpga: OnceLock::new(),
overlay_handler: OnceLock::new(),
}
}
}
impl Platform for XilinxDfxMgrPlatform {
fn fpga(&self, device_handle: &str) -> Result<&dyn Fpga, FpgadError> {
Ok(self
.fpga
.get_or_init(|| XilinxDfxMgrFPGA::new(device_handle)))
}
fn overlay_handler(&self, overlay_handle: &str) -> Result<&dyn OverlayHandler, FpgadError> {
Ok(self
.overlay_handler
.get_or_init(|| XilinxDfxMgrOverlayHandler::new(overlay_handle)))
}
fn status_message(&self) -> Result<String, FpgadError> {
Ok(list_package()?)
}
fn platform_compat_string(&self) -> String {
Self::COMPAT_STRING.into()
}
fn is_available(&self) -> bool {
let available = xilinx_dfx_mgr_helpers::get_dfx_mgr_client_path().is_ok();
if !available {
info!(
"The dfx-mgr-client binary was not found and therefore Xilinx DFX Manager softener isn't available. \
If you'd like to use DFX Manager features, you can install support via: \
`sudo snap install fpgad+dfx-mgr.comp --dangerous` or `sudo apt install dfx-mgr`. \
For now, this will probably use the xlnx-sys platform as fallback."
);
}
available
}
}
pub fn list_package() -> Result<String, FpgadSoftenerError> {
run_dfx_mgr(&["-listPackage"])
}
#[allow(dead_code)]
pub fn load(accel_name: &str) -> Result<String, FpgadSoftenerError> {
run_dfx_mgr(&["-load", accel_name])
}
#[allow(dead_code)]
pub fn remove(slot_handle: Option<&str>) -> Result<String, FpgadSoftenerError> {
match slot_handle {
Some(slot_handle) => Ok(run_dfx_mgr(&["-unload", slot_handle])?),
None => Ok(run_dfx_mgr(&["-unload", "1"])?),
}
}
pub fn load_bitstream(bitstream_path: &Path) -> Result<String, FpgadSoftenerError> {
let path_str = bitstream_path.to_str().ok_or_else(|| {
FpgadSoftenerError::DfxMgr(format!(
"Bitstream path contains invalid UTF-8: {}",
bitstream_path.display()
))
})?;
run_dfx_mgr(&["-b", path_str])
}
pub fn load_overlay(bitstream_path: &Path, dtbo_path: &Path) -> Result<String, FpgadSoftenerError> {
let bitstream_str = bitstream_path.to_str().ok_or_else(|| {
FpgadSoftenerError::DfxMgr(format!(
"Bitstream path contains invalid UTF-8: {}",
bitstream_path.display()
))
})?;
let dtbo_str = dtbo_path.to_str().ok_or_else(|| {
FpgadSoftenerError::DfxMgr(format!(
"DTBO path contains invalid UTF-8: {}",
dtbo_path.display()
))
})?;
run_dfx_mgr(&["-o", dtbo_str, "-b", bitstream_str])
}