use crate::{Handle, Time};
#[repr(u32)]
pub enum CbReason {
ValueChange = vpi_sys::cbValueChange,
Stmt = vpi_sys::cbStmt,
Force = vpi_sys::cbForce,
Release = vpi_sys::cbRelease,
AtStartOfSimTime = vpi_sys::cbAtStartOfSimTime,
ReadWriteSynch = vpi_sys::cbReadWriteSynch,
ReadOnlySynch = vpi_sys::cbReadOnlySynch,
NextSimTime = vpi_sys::cbNextSimTime,
AfterDelay = vpi_sys::cbAfterDelay,
EndOfCompile = vpi_sys::cbEndOfCompile,
StartOfSimulation = vpi_sys::cbStartOfSimulation,
EndOfSimulation = vpi_sys::cbEndOfSimulation,
Error = vpi_sys::cbError,
TchkViolation = vpi_sys::cbTchkViolation,
StartOfSave = vpi_sys::cbStartOfSave,
EndOfSave = vpi_sys::cbEndOfSave,
StartOfRestart = vpi_sys::cbStartOfRestart,
EndOfRestart = vpi_sys::cbEndOfRestart,
StartOfReset = vpi_sys::cbStartOfReset,
EndOfReset = vpi_sys::cbEndOfReset,
EnterInteractive = vpi_sys::cbEnterInteractive,
ExitInteractive = vpi_sys::cbExitInteractive,
InteractiveScopeChange = vpi_sys::cbInteractiveScopeChange,
UnresolvedSystf = vpi_sys::cbUnresolvedSystf,
PLIError = vpi_sys::cbPLIError,
Assign = vpi_sys::cbAssign,
Deassign = vpi_sys::cbDeassign,
Disable = vpi_sys::cbDisable,
Signal = vpi_sys::cbSignal,
NBASynch = vpi_sys::cbNBASynch,
AtEndOfSimTime = vpi_sys::cbAtEndOfSimTime,
#[cfg(feature = "sv")]
StartOfThread = vpi_sys::cbStartOfThread,
#[cfg(feature = "sv")]
EndOfThread = vpi_sys::cbEndOfThread,
#[cfg(feature = "sv")]
EnterThread = vpi_sys::cbEnterThread,
#[cfg(feature = "sv")]
StartOfFrame = vpi_sys::cbStartOfFrame,
#[cfg(feature = "sv")]
EndOfFrame = vpi_sys::cbEndOfFrame,
#[cfg(feature = "sv")]
SizeChange = vpi_sys::cbSizeChange,
#[cfg(feature = "sv")]
AssertionStart = vpi_sys::cbAssertionStart,
#[cfg(feature = "sv")]
AssertionSuccess = vpi_sys::cbAssertionSuccess,
#[cfg(feature = "sv")]
AssertionFailure = vpi_sys::cbAssertionFailure,
#[cfg(feature = "sv")]
AssertionStepSuccess = vpi_sys::cbAssertionStepSuccess,
#[cfg(feature = "sv")]
AssertionStepFailure = vpi_sys::cbAssertionStepFailure,
#[cfg(feature = "sv")]
AssertionDisable = vpi_sys::cbAssertionDisable,
#[cfg(feature = "sv")]
AssertionEnable = vpi_sys::cbAssertionEnable,
#[cfg(feature = "sv")]
AssertionReset = vpi_sys::cbAssertionReset,
#[cfg(feature = "sv")]
AssertionKill = vpi_sys::cbAssertionKill,
#[cfg(feature = "sv")]
AssertionSysInitialized = vpi_sys::cbAssertionSysInitialized,
#[cfg(feature = "sv")]
AssertionSysOn = vpi_sys::cbAssertionSysOn,
#[cfg(feature = "sv")]
AssertionSysOff = vpi_sys::cbAssertionSysOff,
#[cfg(feature = "sv")]
AssertionSysEnd = vpi_sys::cbAssertionSysEnd,
#[cfg(feature = "sv")]
AssertionSysReset = vpi_sys::cbAssertionSysReset,
#[cfg(feature = "sv")]
AssertionVacuousSuccess = vpi_sys::cbAssertionVacuousSuccess,
#[cfg(feature = "sv")]
AssertionDisabledEvaluation = vpi_sys::cbAssertionDisabledEvaluation,
#[cfg(feature = "sv")]
AssertionSysLock = vpi_sys::cbAssertionSysLock,
#[cfg(feature = "sv")]
AssertionSysUnlock = vpi_sys::cbAssertionSysUnlock,
#[cfg(feature = "sv")]
AssertionLock = vpi_sys::cbAssertionLock,
#[cfg(feature = "sv")]
AssertionUnlock = vpi_sys::cbAssertionUnlock,
#[cfg(feature = "sv")]
AssertionEnablePassAction = vpi_sys::cbAssertionEnablePassAction,
#[cfg(feature = "sv")]
AssertionEnableFailAction = vpi_sys::cbAssertionEnableFailAction,
#[cfg(feature = "sv")]
AssertionDisablePassAction = vpi_sys::cbAssertionDisablePassAction,
#[cfg(feature = "sv")]
AssertionDisableFailAction = vpi_sys::cbAssertionDisableFailAction,
#[cfg(feature = "sv")]
AssertionEnableNonvacuousAction = vpi_sys::cbAssertionEnableNonvacuousAction,
#[cfg(feature = "sv")]
AssertionDisableVacuousAction = vpi_sys::cbAssertionDisableVacuousAction,
#[cfg(feature = "sv")]
AssertionSysEnablePassAction = vpi_sys::cbAssertionSysEnablePassAction,
#[cfg(feature = "sv")]
AssertionSysEnableFailAction = vpi_sys::cbAssertionSysEnableFailAction,
#[cfg(feature = "sv")]
AssertionSysDisablePassAction = vpi_sys::cbAssertionSysDisablePassAction,
#[cfg(feature = "sv")]
AssertionSysDisableFailAction = vpi_sys::cbAssertionSysDisableFailAction,
#[cfg(feature = "sv")]
AssertionSysEnableNonvacuousAction = vpi_sys::cbAssertionSysEnableNonvacuousAction,
#[cfg(feature = "sv")]
AssertionSysDisableVacuousAction = vpi_sys::cbAssertionSysDisableVacuousAction,
#[cfg(feature = "sv")]
CreateObj = vpi_sys::cbCreateObj,
#[cfg(feature = "sv")]
ReclaimObj = vpi_sys::cbReclaimObj,
#[cfg(feature = "sv")]
EndOfObject = vpi_sys::cbEndOfObject,
}
pub struct Callback {
pub reason: CbReason,
pub cb_rtn: Option<unsafe extern "C" fn(*mut vpi_sys::t_cb_data) -> i32>,
pub obj: Option<crate::Handle>,
pub time: Option<crate::Time>,
pub value: Option<crate::Value>,
pub user_data: Option<*mut i8>,
}
pub struct CbData {
pub obj: Handle,
}
impl Handle {
pub fn register_cb<F>(&self, reason: CbReason, callback: F) -> Handle
where
F: Fn(&CbData) + 'static,
{
let boxed: Box<F> = Box::new(callback);
let user_data = Box::into_raw(boxed).cast::<std::os::raw::c_void>();
let handle = unsafe {
let mut cb_data = vpi_sys::s_cb_data {
reason: reason as i32,
cb_rtn: Some(trampoline::<F>),
obj: self.as_raw(),
time: std::ptr::null_mut(),
value: std::ptr::null_mut(),
index: 0,
user_data: user_data.cast::<i8>(),
};
vpi_sys::vpi_register_cb(&raw mut cb_data)
};
Handle::from_raw(handle)
}
}
unsafe extern "C" fn trampoline<F>(cb_data: *mut vpi_sys::t_cb_data) -> i32
where
F: Fn(&CbData),
{
if cb_data.is_null() {
return 0; }
let user_data = unsafe { (*cb_data).user_data.cast::<F>() };
if user_data.is_null() {
return 0; }
let mut data = CbData {
obj: Handle::from_raw(unsafe { (*cb_data).obj }),
};
let callback = unsafe { &*user_data };
callback(&data);
data.obj.clear(); 0 }
pub fn register_cb<F>(reason: CbReason, callback: F) -> Handle
where
F: Fn(&CbData) + 'static,
{
let boxed: Box<F> = Box::new(callback);
let user_data = Box::into_raw(boxed).cast::<std::os::raw::c_void>();
let handle = unsafe {
let mut cb_data = vpi_sys::s_cb_data {
reason: reason as i32,
cb_rtn: Some(trampoline::<F>),
obj: std::ptr::null_mut(),
time: std::ptr::null_mut(),
value: std::ptr::null_mut(),
index: 0,
user_data: user_data.cast::<i8>(),
};
vpi_sys::vpi_register_cb(&raw mut cb_data)
};
Handle::from_raw(handle)
}
pub fn register_cb_with_time<F>(reason: CbReason, time: Time, callback: F) -> Handle
where
F: Fn(&CbData) + 'static,
{
let boxed: Box<F> = Box::new(callback);
let user_data = Box::into_raw(boxed).cast::<i8>();
let handle = unsafe {
let mut cb_data = vpi_sys::s_cb_data {
reason: reason as i32,
cb_rtn: Some(trampoline::<F>),
obj: std::ptr::null_mut(),
time: std::ptr::from_mut(&mut time.into()),
value: std::ptr::null_mut(),
index: 0,
user_data,
};
vpi_sys::vpi_register_cb(&raw mut cb_data)
};
Handle::from_raw(handle)
}
pub fn remove_cb(handle: &Handle) {
if !handle.is_null() {
unsafe {
vpi_sys::vpi_remove_cb(handle.as_raw());
let _ = Box::from_raw(handle.as_raw().cast::<i8>());
}
}
}