use std::io;
use std::process::Command;
use std::sync::OnceLock;
use log::trace;
use crate::platforms::platform::Platform;
use crate::platforms::universal_components::universal_fpga::UniversalFPGA;
use crate::platforms::universal_components::universal_overlay_handler::UniversalOverlayHandler;
use crate::softeners::error::FpgadSoftenerError;
use fpgad_macros::platform;
#[platform(compat_string = "xlnx,zynqmp-pcap-fpga,versal-fpga,zynq-devcfg-1.0")]
pub struct XilinxDfxMgrPlatform {
fpga: OnceLock<UniversalFPGA>,
overlay_handler: OnceLock<UniversalOverlayHandler>,
}
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 crate::platforms::platform::Fpga, crate::error::FpgadError> {
Ok(self.fpga.get_or_init(|| UniversalFPGA::new(device_handle)))
}
fn overlay_handler(
&self,
overlay_handle: &str,
) -> Result<&dyn crate::platforms::platform::OverlayHandler, crate::error::FpgadError> {
Ok(self
.overlay_handler
.get_or_init(|| UniversalOverlayHandler::new(overlay_handle)))
}
}
#[allow(dead_code)]
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: u32) -> Result<String, FpgadSoftenerError> {
run_dfx_mgr(&["-remove", &slot.to_string()])
}
#[allow(dead_code)]
pub fn list_uio(slot: Option<u32>, uio_name: Option<&str>) -> Result<String, FpgadSoftenerError> {
let mut args = vec!["-listUIO"];
if let Some(name) = uio_name {
args.push(name);
}
if let Some(slot) = slot {
let s_slot = slot.to_string();
args.push(&s_slot);
run_dfx_mgr(&args)
} else {
run_dfx_mgr(&args)
}
}
#[allow(dead_code)]
pub fn list_irbuf(slot: Option<u32>) -> Result<String, FpgadSoftenerError> {
let mut args = vec!["-listIRbuf"];
if let Some(slot) = slot {
let s_slot = slot.to_string();
args.push(s_slot.as_str());
run_dfx_mgr(&args)
} else {
run_dfx_mgr(&args)
}
}
#[allow(dead_code)]
pub fn set_irbuf(a: u32, b: u32) -> Result<String, FpgadSoftenerError> {
run_dfx_mgr(&["-setIRbuf", &format!("{a},{b}")])
}
#[allow(dead_code)]
pub fn alloc_buffer(size: u64) -> Result<String, FpgadSoftenerError> {
run_dfx_mgr(&["-allocBuffer", &size.to_string()])
}
#[allow(dead_code)]
pub fn free_buffer(pa: u64) -> Result<String, FpgadSoftenerError> {
run_dfx_mgr(&["-freeBuffer", &pa.to_string()])
}
#[allow(dead_code)]
pub fn get_fds(slot: u32) -> Result<String, FpgadSoftenerError> {
run_dfx_mgr(&["-getFDs", &slot.to_string()])
}
#[allow(dead_code)]
pub fn get_rm_info() -> Result<String, FpgadSoftenerError> {
run_dfx_mgr(&["-getRMInfo"])
}
#[allow(dead_code)]
pub fn get_shell_fd() -> Result<String, FpgadSoftenerError> {
run_dfx_mgr(&["-getShellFD"])
}
#[allow(dead_code)]
pub fn get_clock_fd() -> Result<String, FpgadSoftenerError> {
run_dfx_mgr(&["-getClockFD"])
}
fn run_dfx_mgr(args: &[&str]) -> Result<String, FpgadSoftenerError> {
let output = Command::new("sudo")
.arg("dfx-mgr-client")
.args(args)
.output()
.map_err(FpgadSoftenerError::DfxMgr)?;
if output.status.success() {
Ok(String::from_utf8_lossy(&output.stdout).to_string())
} else {
Err(FpgadSoftenerError::DfxMgr(io::Error::other(
String::from_utf8_lossy(&output.stderr).to_string(),
)))
}
}