#![allow(clippy::arc_with_non_send_sync)]
use std::{
ffi::{CStr, CString},
sync::{Arc, RwLock, RwLockReadGuard, RwLockWriteGuard},
};
use xlsynth_sys::{
CIrAnalysis, CIrBits, CIrFunction, CIrFunctionJit, CIrFunctionType, CIrIntervalSet, CIrPackage,
CIrType, CIrValue, CScheduleAndCodegenResult, CTraceMessage, XlsFormatPreference,
};
use crate::{
XlsIrBits, XlsIrValue, XlsynthError,
ir_package::{IrPackagePtr, IrType, ScheduleAndCodegenResult},
};
macro_rules! xls_ffi_call {
($func:path $(, $arg:expr )* ; $out:ident) => {{
unsafe {
let mut error_out: *mut std::os::raw::c_char = std::ptr::null_mut();
let success = $func($($arg,)* &mut error_out, &mut $out);
if success {
Ok(())
} else {
Err(XlsynthError(c_str_to_rust(error_out)))
}
}
}};
}
macro_rules! xls_ffi_call_noreturn {
($func:path $(, $arg:expr )*) => {{
unsafe {
let mut error_out: *mut std::os::raw::c_char = std::ptr::null_mut();
let success = $func($($arg,)* &mut error_out);
if success {
Ok(())
} else {
Err(XlsynthError(c_str_to_rust(error_out)))
}
}
}};
}
pub(crate) fn xls_package_to_string(p: *const CIrPackage) -> Result<String, XlsynthError> {
unsafe {
let mut c_str_out: *mut std::os::raw::c_char = std::ptr::null_mut();
let success = xlsynth_sys::xls_package_to_string(p, &mut c_str_out);
if success {
Ok(c_str_to_rust(c_str_out))
} else {
Err(XlsynthError(
"Failed to convert XLS package to string via C API".to_string(),
))
}
}
}
pub(crate) fn xls_function_to_string(f: *const CIrFunction) -> Result<String, XlsynthError> {
unsafe {
let mut c_str_out: *mut std::os::raw::c_char = std::ptr::null_mut();
let success = xlsynth_sys::xls_function_to_string(f, &mut c_str_out);
if success {
Ok(c_str_to_rust(c_str_out))
} else {
Err(XlsynthError(
"Failed to convert XLS function to string via C API".to_string(),
))
}
}
}
pub(crate) fn xls_function_to_z3_smtlib(
function: *mut CIrFunction,
) -> Result<String, XlsynthError> {
let mut c_str_out: *mut std::os::raw::c_char = std::ptr::null_mut();
xls_ffi_call!(xlsynth_sys::xls_function_to_z3_smtlib, function; c_str_out)?;
unsafe { Ok(c_str_to_rust(c_str_out)) }
}
pub(crate) unsafe fn c_str_to_rust_no_dealloc(xls_c_str: *mut std::os::raw::c_char) -> String {
if xls_c_str.is_null() {
String::new()
} else {
let c_str: &CStr = unsafe { CStr::from_ptr(xls_c_str) };
String::from_utf8_lossy(c_str.to_bytes()).to_string()
}
}
pub(crate) unsafe fn c_str_to_rust(xls_c_str: *mut std::os::raw::c_char) -> String {
let result = unsafe { c_str_to_rust_no_dealloc(xls_c_str) };
unsafe {
xlsynth_sys::xls_c_str_free(xls_c_str);
}
result
}
fn cstring_and_ptr(name: &str) -> (CString, *const std::os::raw::c_char) {
let cstr = CString::new(name).unwrap();
let ptr = cstr.as_ptr();
(cstr, ptr)
}
fn optional_cstring_and_ptr(name: Option<&str>) -> (Option<CString>, *const std::os::raw::c_char) {
if let Some(s) = name {
let cstr = CString::new(s).unwrap();
let ptr = cstr.as_ptr();
(Some(cstr), ptr)
} else {
(None, std::ptr::null())
}
}
pub(crate) fn xls_value_free(p: *mut CIrValue) {
unsafe { xlsynth_sys::xls_value_free(p) }
}
pub(crate) fn xls_package_free(p: *mut CIrPackage) {
unsafe { xlsynth_sys::xls_package_free(p) }
}
pub(crate) fn xls_value_to_string(p: *mut CIrValue) -> Result<String, XlsynthError> {
unsafe {
let mut c_str_out: *mut std::os::raw::c_char = std::ptr::null_mut();
let success = xlsynth_sys::xls_value_to_string(p, &mut c_str_out);
if success {
Ok(c_str_to_rust(c_str_out))
} else {
Err(XlsynthError(
"Failed to convert XLS value to string via C API".to_string(),
))
}
}
}
pub(crate) fn xls_value_get_element(
p: *mut CIrValue,
index: usize,
) -> Result<XlsIrValue, XlsynthError> {
let mut element_out: *mut CIrValue = std::ptr::null_mut();
xls_ffi_call!(xlsynth_sys::xls_value_get_element, p, index; element_out)?;
Ok(XlsIrValue { ptr: element_out })
}
pub(crate) fn xls_value_get_element_count(p: *const CIrValue) -> Result<usize, XlsynthError> {
let mut count: i64 = 0;
xls_ffi_call!(xlsynth_sys::xls_value_get_element_count, p; count)?;
Ok(count as usize)
}
pub(crate) fn xls_value_make_ubits(
value: u64,
bit_count: usize,
) -> Result<XlsIrValue, XlsynthError> {
let mut result: *mut CIrValue = std::ptr::null_mut();
xls_ffi_call!(xlsynth_sys::xls_value_make_ubits, bit_count as i64, value; result)?;
Ok(XlsIrValue { ptr: result })
}
pub(crate) fn xls_value_make_sbits(
value: i64,
bit_count: usize,
) -> Result<XlsIrValue, XlsynthError> {
let mut result: *mut CIrValue = std::ptr::null_mut();
xls_ffi_call!(xlsynth_sys::xls_value_make_sbits, bit_count as i64, value; result)?;
Ok(XlsIrValue { ptr: result })
}
pub(crate) fn xls_value_make_token() -> XlsIrValue {
let result = unsafe { xlsynth_sys::xls_value_make_token() };
assert!(!result.is_null());
XlsIrValue { ptr: result }
}
pub(crate) fn xls_value_make_tuple(elements: &[XlsIrValue]) -> XlsIrValue {
unsafe {
let elements_ptrs: Vec<*const CIrValue> =
elements.iter().map(|v| v.ptr as *const CIrValue).collect();
let result = xlsynth_sys::xls_value_make_tuple(elements_ptrs.len(), elements_ptrs.as_ptr());
assert!(!result.is_null());
XlsIrValue { ptr: result }
}
}
pub(crate) fn xls_value_make_array(elements: &[XlsIrValue]) -> Result<XlsIrValue, XlsynthError> {
let elements_ptrs: Vec<*const CIrValue> =
elements.iter().map(|v| v.ptr as *const CIrValue).collect();
let mut result: *mut CIrValue = std::ptr::null_mut();
xls_ffi_call!(xlsynth_sys::xls_value_make_array, elements_ptrs.len(), elements_ptrs.as_ptr(); result)?;
Ok(XlsIrValue { ptr: result })
}
pub(crate) fn xls_bits_to_debug_str(p: *const CIrBits) -> String {
unsafe {
let c_str_out = xlsynth_sys::xls_bits_to_debug_string(p);
c_str_to_rust(c_str_out)
}
}
pub(crate) fn xls_bits_make_ubits(bit_count: usize, value: u64) -> Result<XlsIrBits, XlsynthError> {
let mut result: *mut CIrBits = std::ptr::null_mut();
xls_ffi_call!(xlsynth_sys::xls_bits_make_ubits, bit_count as i64, value; result)?;
Ok(XlsIrBits { ptr: result })
}
pub(crate) fn xls_bits_make_sbits(bit_count: usize, value: i64) -> Result<XlsIrBits, XlsynthError> {
let mut result: *mut CIrBits = std::ptr::null_mut();
xls_ffi_call!(xlsynth_sys::xls_bits_make_sbits, bit_count as i64, value; result)?;
Ok(XlsIrBits { ptr: result })
}
pub(crate) fn xls_bits_make_bits_from_bytes(
bit_count: usize,
bytes: &[u8],
) -> Result<XlsIrBits, XlsynthError> {
unsafe {
let mut error_out: *mut std::os::raw::c_char = std::ptr::null_mut();
let mut bits_out: *mut CIrBits = std::ptr::null_mut();
let success = xlsynth_sys::xls_bits_make_bits_from_bytes(
bit_count,
bytes.as_ptr(),
bytes.len(),
&mut error_out,
&mut bits_out,
);
if !success {
return Err(XlsynthError(c_str_to_rust(error_out)));
}
Ok(XlsIrBits { ptr: bits_out })
}
}
pub(crate) fn xls_value_get_bits(p: *const CIrValue) -> Result<XlsIrBits, XlsynthError> {
let mut result: *mut CIrBits = std::ptr::null_mut();
xls_ffi_call!(xlsynth_sys::xls_value_get_bits, p; result)?;
Ok(XlsIrBits { ptr: result })
}
pub(crate) fn xls_format_preference_from_string(
s: &str,
) -> Result<XlsFormatPreference, XlsynthError> {
let c_str = CString::new(s).unwrap();
let mut result_out: XlsFormatPreference = -1;
xls_ffi_call!(xlsynth_sys::xls_format_preference_from_string, c_str.as_ptr(); result_out)?;
Ok(result_out)
}
pub(crate) fn xls_value_to_string_format_preference(
p: *mut CIrValue,
fmt: XlsFormatPreference,
) -> Result<String, XlsynthError> {
let mut c_str_out: *mut std::os::raw::c_char = std::ptr::null_mut();
xls_ffi_call!(xlsynth_sys::xls_value_to_string_format_preference, p, fmt; c_str_out)?;
Ok(unsafe { c_str_to_rust(c_str_out) })
}
pub(crate) fn xls_bits_to_string(
p: *const CIrBits,
fmt: XlsFormatPreference,
include_bit_count: bool,
) -> Result<String, XlsynthError> {
let mut c_str_out: *mut std::os::raw::c_char = std::ptr::null_mut();
xls_ffi_call!(xlsynth_sys::xls_bits_to_string, p, fmt, include_bit_count; c_str_out)?;
Ok(unsafe { c_str_to_rust(c_str_out) })
}
pub(crate) fn xls_bits_to_bytes(p: *const CIrBits) -> Result<Vec<u8>, XlsynthError> {
unsafe {
let mut error_out: *mut std::os::raw::c_char = std::ptr::null_mut();
let mut bytes_out: *mut u8 = std::ptr::null_mut();
let mut byte_count_out: usize = 0;
let success =
xlsynth_sys::xls_bits_to_bytes(p, &mut error_out, &mut bytes_out, &mut byte_count_out);
if !success {
return Err(XlsynthError(c_str_to_rust(error_out)));
}
let slice = std::slice::from_raw_parts(bytes_out, byte_count_out);
let vec = slice.to_vec();
xlsynth_sys::xls_bytes_free(bytes_out);
Ok(vec)
}
}
pub(crate) fn xls_bits_to_uint64(p: *const CIrBits) -> Result<u64, XlsynthError> {
let mut value_out: u64 = 0;
xls_ffi_call!(xlsynth_sys::xls_bits_to_uint64, p; value_out)?;
Ok(value_out)
}
pub(crate) fn xls_bits_to_int64(p: *const CIrBits) -> Result<i64, XlsynthError> {
let mut value_out: i64 = 0;
xls_ffi_call!(xlsynth_sys::xls_bits_to_int64, p; value_out)?;
Ok(value_out)
}
pub(crate) fn xls_value_eq(
lhs: *const CIrValue,
rhs: *const CIrValue,
) -> Result<bool, XlsynthError> {
unsafe { Ok(xlsynth_sys::xls_value_eq(lhs, rhs)) }
}
pub(crate) fn xls_parse_ir_package(
ir: &str,
filename: Option<&str>,
) -> Result<crate::ir_package::IrPackage, XlsynthError> {
let ir_cstring = CString::new(ir).unwrap();
let (_filename_cstr, filename_ptr) = optional_cstring_and_ptr(filename);
let mut xls_package_out: *mut CIrPackage = std::ptr::null_mut();
xls_ffi_call!(xlsynth_sys::xls_parse_ir_package, ir_cstring.as_ptr(), filename_ptr; xls_package_out)?;
let package = crate::ir_package::IrPackage {
ptr: Arc::new(RwLock::new(IrPackagePtr(xls_package_out))),
filename: filename.map(|s| s.to_string()),
};
Ok(package)
}
pub(crate) fn xls_ir_analysis_create_from_package_with_options(
p: *mut CIrPackage,
options: Option<&xlsynth_sys::XlsIrAnalysisOptions>,
) -> Result<*mut CIrAnalysis, XlsynthError> {
let mut out: *mut CIrAnalysis = std::ptr::null_mut();
let options_ptr: *const xlsynth_sys::XlsIrAnalysisOptions = options
.map_or(std::ptr::null(), |o| {
o as *const xlsynth_sys::XlsIrAnalysisOptions
});
xls_ffi_call!(
xlsynth_sys::xls_ir_analysis_create_from_package_with_options,
p,
options_ptr;
out
)?;
Ok(out)
}
pub(crate) fn xls_ir_analysis_get_known_bits_for_node_id(
a: *const CIrAnalysis,
node_id: i64,
) -> Result<(XlsIrBits, XlsIrBits), XlsynthError> {
unsafe {
let mut error_out: *mut std::os::raw::c_char = std::ptr::null_mut();
let mut known_mask_out: *mut CIrBits = std::ptr::null_mut();
let mut known_value_out: *mut CIrBits = std::ptr::null_mut();
let success = xlsynth_sys::xls_ir_analysis_get_known_bits_for_node_id(
a,
node_id,
&mut error_out,
&mut known_mask_out,
&mut known_value_out,
);
if success {
Ok((
XlsIrBits {
ptr: known_mask_out,
},
XlsIrBits {
ptr: known_value_out,
},
))
} else {
Err(XlsynthError(c_str_to_rust(error_out)))
}
}
}
pub(crate) fn xls_ir_analysis_get_intervals_for_node_id(
a: *const CIrAnalysis,
node_id: i64,
) -> Result<*mut CIrIntervalSet, XlsynthError> {
let mut intervals_out: *mut CIrIntervalSet = std::ptr::null_mut();
xls_ffi_call!(
xlsynth_sys::xls_ir_analysis_get_intervals_for_node_id,
a,
node_id;
intervals_out
)?;
Ok(intervals_out)
}
pub(crate) fn xls_ir_analysis_at_most_one_bit_true(
a: *const CIrAnalysis,
node_id: i64,
) -> Result<bool, XlsynthError> {
let mut result_out = false;
xls_ffi_call!(
xlsynth_sys::xls_ir_analysis_at_most_one_bit_true,
a,
node_id;
result_out
)?;
Ok(result_out)
}
pub(crate) fn xls_ir_analysis_at_least_one_bit_true(
a: *const CIrAnalysis,
node_id: i64,
) -> Result<bool, XlsynthError> {
let mut result_out = false;
xls_ffi_call!(
xlsynth_sys::xls_ir_analysis_at_least_one_bit_true,
a,
node_id;
result_out
)?;
Ok(result_out)
}
pub(crate) fn xls_ir_analysis_exactly_one_bit_true(
a: *const CIrAnalysis,
node_id: i64,
) -> Result<bool, XlsynthError> {
let mut result_out = false;
xls_ffi_call!(
xlsynth_sys::xls_ir_analysis_exactly_one_bit_true,
a,
node_id;
result_out
)?;
Ok(result_out)
}
pub(crate) fn xls_ir_analysis_known_not_equals(
a: *const CIrAnalysis,
lhs_node_id: i64,
lhs_bit_index: i64,
rhs_node_id: i64,
rhs_bit_index: i64,
) -> Result<bool, XlsynthError> {
let mut result_out = false;
xls_ffi_call!(
xlsynth_sys::xls_ir_analysis_known_not_equals,
a,
lhs_node_id,
lhs_bit_index,
rhs_node_id,
rhs_bit_index;
result_out
)?;
Ok(result_out)
}
pub(crate) fn xls_ir_analysis_implies(
a: *const CIrAnalysis,
lhs_node_id: i64,
lhs_bit_index: i64,
rhs_node_id: i64,
rhs_bit_index: i64,
) -> Result<bool, XlsynthError> {
let mut result_out = false;
xls_ffi_call!(
xlsynth_sys::xls_ir_analysis_implies,
a,
lhs_node_id,
lhs_bit_index,
rhs_node_id,
rhs_bit_index;
result_out
)?;
Ok(result_out)
}
pub(crate) fn xls_interval_set_get_interval_bounds(
s: *const CIrIntervalSet,
i: i64,
) -> Result<(XlsIrBits, XlsIrBits), XlsynthError> {
unsafe {
let mut error_out: *mut std::os::raw::c_char = std::ptr::null_mut();
let mut lo_out: *mut CIrBits = std::ptr::null_mut();
let mut hi_out: *mut CIrBits = std::ptr::null_mut();
let success = xlsynth_sys::xls_interval_set_get_interval_bounds(
s,
i,
&mut error_out,
&mut lo_out,
&mut hi_out,
);
if success {
Ok((XlsIrBits { ptr: lo_out }, XlsIrBits { ptr: hi_out }))
} else {
Err(XlsynthError(c_str_to_rust(error_out)))
}
}
}
pub(crate) fn xls_package_new(name: &str) -> Result<crate::ir_package::IrPackage, XlsynthError> {
let (_name_cstr, name_ptr) = cstring_and_ptr(name);
let xls_package_out: *mut CIrPackage = unsafe { xlsynth_sys::xls_package_create(name_ptr) };
Ok(crate::ir_package::IrPackage {
ptr: Arc::new(RwLock::new(IrPackagePtr(xls_package_out))),
filename: None,
})
}
pub(crate) fn xls_type_to_string(t: *const CIrType) -> Result<String, XlsynthError> {
let mut c_str_out: *mut std::os::raw::c_char = std::ptr::null_mut();
xls_ffi_call!(xlsynth_sys::xls_type_to_string, t; c_str_out)?;
Ok(unsafe { c_str_to_rust(c_str_out) })
}
pub(crate) fn xls_type_get_flat_bit_count(t: *const CIrType) -> u64 {
let bit_count = unsafe { xlsynth_sys::xls_type_get_flat_bit_count(t) };
assert!(bit_count >= 0, "bit count must be non-negative");
bit_count as u64
}
pub(crate) fn xls_package_set_top_by_name(
package: *mut CIrPackage,
name: &str,
) -> Result<(), XlsynthError> {
let (_name_cstr, name_ptr) = cstring_and_ptr(name);
xls_ffi_call_noreturn!(xlsynth_sys::xls_package_set_top_by_name, package, name_ptr)?;
Ok(())
}
pub(crate) fn xls_verify_package(package: *mut CIrPackage) -> Result<(), XlsynthError> {
xls_ffi_call_noreturn!(xlsynth_sys::xls_verify_package, package)?;
Ok(())
}
pub(crate) fn xls_package_get_bits_type(package: *mut CIrPackage, bit_count: u64) -> *mut CIrType {
unsafe { xlsynth_sys::xls_package_get_bits_type(package, bit_count as i64) }
}
pub(crate) fn xls_package_get_tuple_type(
package: *mut CIrPackage,
members: &[IrType],
) -> *mut CIrType {
let mut members_ptrs: Vec<*mut CIrType> = members.iter().map(|v| v.ptr).collect();
let members_ptr = members_ptrs.as_mut_ptr();
let member_count = members_ptrs.len() as i64;
unsafe { xlsynth_sys::xls_package_get_tuple_type(package, members_ptr, member_count) }
}
pub(crate) fn xls_package_get_array_type(
package: *mut CIrPackage,
element_type: *mut CIrType,
size: i64,
) -> *mut CIrType {
unsafe { xlsynth_sys::xls_package_get_array_type(package, element_type, size) }
}
pub(crate) fn xls_package_get_token_type(package: *mut CIrPackage) -> *mut CIrType {
unsafe { xlsynth_sys::xls_package_get_token_type(package) }
}
pub(crate) fn xls_package_get_type_for_value(
package: *mut CIrPackage,
value: *mut CIrValue,
) -> Result<*mut CIrType, XlsynthError> {
let mut result_out: *mut CIrType = std::ptr::null_mut();
xls_ffi_call!(xlsynth_sys::xls_package_get_type_for_value, package, value; result_out)?;
Ok(result_out)
}
pub(crate) fn xls_package_get_function(
package: &Arc<RwLock<IrPackagePtr>>,
guard: RwLockReadGuard<IrPackagePtr>,
function_name: &str,
) -> Result<crate::ir_package::IrFunction, XlsynthError> {
let function_name = CString::new(function_name).unwrap();
let mut result_out: *mut CIrFunction = std::ptr::null_mut();
xls_ffi_call!(xlsynth_sys::xls_package_get_function, guard.const_c_ptr(), function_name.as_ptr(); result_out)?;
Ok(crate::ir_package::IrFunction {
parent: package.clone(),
ptr: result_out,
})
}
pub(crate) fn xls_package_get_functions(
package: &Arc<RwLock<IrPackagePtr>>,
guard: RwLockWriteGuard<IrPackagePtr>,
) -> Result<Vec<crate::ir_package::IrFunction>, XlsynthError> {
unsafe {
let mut error_out: *mut std::os::raw::c_char = std::ptr::null_mut();
let mut result_out: *mut *mut CIrFunction = std::ptr::null_mut();
let mut count_out: libc::size_t = 0;
let success = xlsynth_sys::xls_package_get_functions(
guard.mut_c_ptr(),
&mut error_out,
&mut result_out,
&mut count_out,
);
if !success {
return Err(XlsynthError(c_str_to_rust(error_out)));
}
let functions = if result_out.is_null() || count_out == 0 {
Vec::new()
} else {
let raw_slice = std::slice::from_raw_parts(result_out, count_out);
raw_slice
.iter()
.map(|&ptr| crate::ir_package::IrFunction {
parent: package.clone(),
ptr,
})
.collect()
};
if !result_out.is_null() {
xlsynth_sys::xls_function_ptr_array_free(result_out);
}
Ok(functions)
}
}
pub(crate) fn xls_function_get_type(
_package_write_guard: &RwLockWriteGuard<IrPackagePtr>,
function: *const CIrFunction,
) -> Result<*mut CIrFunctionType, XlsynthError> {
let mut xls_fn_type_out: *mut CIrFunctionType = std::ptr::null_mut();
xls_ffi_call!(xlsynth_sys::xls_function_get_type, function; xls_fn_type_out)?;
Ok(xls_fn_type_out)
}
pub(crate) fn xls_function_type_to_string(
t: *const CIrFunctionType,
) -> Result<String, XlsynthError> {
let mut c_str_out: *mut std::os::raw::c_char = std::ptr::null_mut();
xls_ffi_call!(xlsynth_sys::xls_function_type_to_string, t; c_str_out)?;
Ok(unsafe { c_str_to_rust(c_str_out) })
}
pub(crate) fn xls_function_get_name(function: *const CIrFunction) -> Result<String, XlsynthError> {
let mut c_str_out: *mut std::os::raw::c_char = std::ptr::null_mut();
xls_ffi_call!(xlsynth_sys::xls_function_get_name, function; c_str_out)?;
Ok(unsafe { c_str_to_rust(c_str_out) })
}
pub(crate) fn xls_interpret_function(
_package_guard: &RwLockReadGuard<IrPackagePtr>,
function: *const CIrFunction,
args: &[XlsIrValue],
) -> Result<XlsIrValue, XlsynthError> {
let args_ptrs: Vec<*const CIrValue> =
args.iter().map(|v| -> *const CIrValue { v.ptr }).collect();
let argc = args_ptrs.len();
let mut result_out: *mut CIrValue = std::ptr::null_mut();
xls_ffi_call!(xlsynth_sys::xls_interpret_function, function, argc, args_ptrs.as_ptr(); result_out)?;
Ok(XlsIrValue { ptr: result_out })
}
pub(crate) fn xls_optimize_ir(ir: &str, top: &str) -> Result<String, XlsynthError> {
let ir = CString::new(ir).unwrap();
let top = CString::new(top).unwrap();
let mut ir_out: *mut std::os::raw::c_char = std::ptr::null_mut();
xls_ffi_call!(xlsynth_sys::xls_optimize_ir, ir.as_ptr(), top.as_ptr(); ir_out)?;
let ir_str = unsafe { c_str_to_rust(ir_out) };
Ok(ir_str)
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct TraceMessage {
pub message: String,
pub verbosity: i64,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct RunResult {
pub value: XlsIrValue,
pub trace_messages: Vec<TraceMessage>,
pub assert_messages: Vec<String>,
}
unsafe fn trace_messages_to_rust(
c_trace_messages: *mut CTraceMessage,
count: usize,
) -> Vec<TraceMessage> {
if c_trace_messages.is_null() {
return Vec::new();
}
let mut trace_messages: Vec<TraceMessage> = Vec::new();
for i in 0..count {
let trace_message: &CTraceMessage = unsafe { &*c_trace_messages.wrapping_add(i) };
trace_messages.push(TraceMessage {
message: unsafe { c_str_to_rust_no_dealloc(trace_message.message) },
verbosity: trace_message.verbosity,
});
}
unsafe {
xlsynth_sys::xls_trace_messages_free(c_trace_messages, count);
}
trace_messages
}
pub(crate) unsafe fn c_strs_to_rust(
c_strs: *mut *mut std::os::raw::c_char,
count: usize,
) -> Vec<String> {
let mut result: Vec<String> = Vec::new();
for i in 0..count {
let xls_c_str: *mut std::os::raw::c_char = unsafe { *c_strs.wrapping_add(i) };
result.push(unsafe { c_str_to_rust_no_dealloc(xls_c_str) });
}
if !c_strs.is_null() && count > 0 {
unsafe {
xlsynth_sys::xls_c_strs_free(c_strs, count);
}
}
result
}
pub(crate) fn xls_make_function_jit(
_package_guard: &RwLockReadGuard<IrPackagePtr>,
function: *const CIrFunction,
) -> Result<*mut CIrFunctionJit, XlsynthError> {
let mut ptr: *mut CIrFunctionJit = std::ptr::null_mut();
xls_ffi_call!(xlsynth_sys::xls_make_function_jit, function; ptr)?;
Ok(ptr)
}
pub(crate) fn xls_function_jit_run(
_package_guard: &RwLockReadGuard<IrPackagePtr>,
jit: *const CIrFunctionJit,
args: &[XlsIrValue],
) -> Result<RunResult, XlsynthError> {
let mut result_out: *mut CIrValue = std::ptr::null_mut();
let mut error_out: *mut std::os::raw::c_char = std::ptr::null_mut();
let argc = args.len();
let args_ptrs: Vec<*const CIrValue> =
args.iter().map(|v| -> *const CIrValue { v.ptr }).collect();
let mut trace_messages_out: *mut CTraceMessage = std::ptr::null_mut();
let mut trace_messages_count: usize = 0;
let mut assert_messages_out: *mut *mut std::os::raw::c_char = std::ptr::null_mut();
let mut assert_messages_count: usize = 0;
let success = unsafe {
xlsynth_sys::xls_function_jit_run(
jit,
argc,
args_ptrs.as_ptr(),
&mut error_out,
&mut trace_messages_out,
&mut trace_messages_count,
&mut assert_messages_out,
&mut assert_messages_count,
&mut result_out,
)
};
if !success {
let error_message = unsafe { c_str_to_rust(error_out) };
return Err(XlsynthError(format!(
"Failed to run JIT function: {error_message}"
)));
}
let trace_messages =
unsafe { trace_messages_to_rust(trace_messages_out, trace_messages_count) };
let assert_messages = unsafe { c_strs_to_rust(assert_messages_out, assert_messages_count) };
Ok(RunResult {
value: XlsIrValue { ptr: result_out },
trace_messages,
assert_messages,
})
}
pub(crate) fn xls_mangle_dslx_name(
module_name: &str,
function_name: &str,
) -> Result<String, XlsynthError> {
let module_name = CString::new(module_name).unwrap();
let function_name = CString::new(function_name).unwrap();
let mut mangled_out: *mut std::os::raw::c_char = std::ptr::null_mut();
xls_ffi_call!(xlsynth_sys::xls_mangle_dslx_name, module_name.as_ptr(), function_name.as_ptr(); mangled_out)?;
Ok(unsafe { c_str_to_rust(mangled_out) })
}
pub(crate) fn xls_mangle_dslx_name_full(
module_name: &str,
function_name: &str,
convention: crate::DslxCallingConvention,
free_keys: &[&str],
param_env: Option<&crate::dslx::ParametricEnv>,
scope: Option<&str>,
) -> Result<String, XlsynthError> {
let module_c = std::ffi::CString::new(module_name).unwrap();
let function_c = std::ffi::CString::new(function_name).unwrap();
let free_key_cstrs: Vec<std::ffi::CString> = free_keys
.iter()
.map(|s| std::ffi::CString::new((*s).as_bytes()).unwrap())
.collect();
let free_key_ptrs: Vec<*const std::os::raw::c_char> =
free_key_cstrs.iter().map(|s| s.as_ptr()).collect();
let free_keys_ptr = if free_key_ptrs.is_empty() {
std::ptr::null()
} else {
free_key_ptrs.as_ptr()
};
let (_scope_cstr_opt, scope_ptr) = optional_cstring_and_ptr(scope);
let cc: xlsynth_sys::XlsCallingConvention = convention.into();
let mut mangled_out: *mut std::os::raw::c_char = std::ptr::null_mut();
xls_ffi_call!(
xlsynth_sys::xls_mangle_dslx_name_full,
module_c.as_ptr(),
function_c.as_ptr(),
cc,
free_keys_ptr,
free_key_ptrs.len(),
param_env.map(|e| e.ptr as *const _).unwrap_or(std::ptr::null()),
scope_ptr;
mangled_out
)?;
Ok(unsafe { c_str_to_rust(mangled_out) })
}
pub(crate) fn xls_schedule_and_codegen_package(
_package: &Arc<RwLock<IrPackagePtr>>,
guard: RwLockWriteGuard<IrPackagePtr>,
scheduling_options_flags_proto_str: &str,
codegen_flags_proto_str: &str,
with_delay_model: bool,
) -> Result<ScheduleAndCodegenResult, XlsynthError> {
let scheduling_options_flags_proto = CString::new(scheduling_options_flags_proto_str).unwrap();
let codegen_flags_proto = CString::new(codegen_flags_proto_str).unwrap();
let mut result_out: *mut CScheduleAndCodegenResult = std::ptr::null_mut();
xls_ffi_call!(xlsynth_sys::xls_schedule_and_codegen_package,
guard.mut_c_ptr(),
scheduling_options_flags_proto.as_ptr(),
codegen_flags_proto.as_ptr(),
with_delay_model;
result_out
)?;
assert!(!result_out.is_null());
Ok(ScheduleAndCodegenResult { ptr: result_out })
}
pub(crate) fn xls_function_type_param_count(t: *mut xlsynth_sys::CIrFunctionType) -> i64 {
unsafe { xlsynth_sys::xls_function_type_get_param_count(t) }
}
pub(crate) fn xls_function_type_get_param_type(
t: *mut xlsynth_sys::CIrFunctionType,
index: usize,
) -> Result<*mut xlsynth_sys::CIrType, XlsynthError> {
let mut error_out: *mut std::os::raw::c_char = std::ptr::null_mut();
let mut type_out: *mut xlsynth_sys::CIrType = std::ptr::null_mut();
let success = unsafe {
xlsynth_sys::xls_function_type_get_param_type(t, index, &mut error_out, &mut type_out)
};
if success {
Ok(type_out)
} else {
Err(XlsynthError(unsafe { c_str_to_rust(error_out) }))
}
}
pub(crate) fn xls_function_type_get_return_type(
t: *mut xlsynth_sys::CIrFunctionType,
) -> *mut xlsynth_sys::CIrType {
unsafe { xlsynth_sys::xls_function_type_get_return_type(t) }
}
pub(crate) fn xls_function_get_param_name(
f: *mut xlsynth_sys::CIrFunction,
index: usize,
) -> Result<String, XlsynthError> {
let mut error_out: *mut std::os::raw::c_char = std::ptr::null_mut();
let mut name_out: *mut std::os::raw::c_char = std::ptr::null_mut();
let success = unsafe {
xlsynth_sys::xls_function_get_param_name(f, index, &mut error_out, &mut name_out)
};
if success {
Ok(unsafe { c_str_to_rust(name_out) })
} else {
Err(XlsynthError(unsafe { c_str_to_rust(error_out) }))
}
}