use std::{any::Any, sync::Arc};
use num_bigint::BigUint;
pub use crate::SimulatorErrorCode;
use crate::{AbsoluteAddr, MemoryLayout, RuntimeEventBuffer, SignalRef};
pub trait EventHandle: Copy + std::fmt::Debug {
fn id(&self) -> usize;
fn addr(&self) -> AbsoluteAddr;
}
pub trait SimBackend {
type Event: EventHandle;
fn eval_comb(&mut self) -> Result<(), SimulatorErrorCode>;
fn eval_apply_ff_at(&mut self, event: Self::Event) -> Result<(), SimulatorErrorCode>;
fn eval_comb_apply_ff_at(&mut self, event: Self::Event) -> Result<(), SimulatorErrorCode> {
self.eval_comb()?;
self.eval_apply_ff_at(event)
}
fn eval_comb_apply_ff_many_at(
&mut self,
event: Self::Event,
count: u64,
) -> (u64, Result<(), SimulatorErrorCode>) {
if count == 0 {
return (0, Ok(()));
}
(1, self.eval_comb_apply_ff_at(event))
}
fn eval_only_ff_at(&mut self, event: Self::Event) -> Result<(), SimulatorErrorCode>;
fn apply_ff_at(&mut self, event: Self::Event) -> Result<(), SimulatorErrorCode>;
fn resolve_signal(&self, addr: &AbsoluteAddr) -> SignalRef;
fn resolve_event(&self, addr: &AbsoluteAddr) -> Self::Event;
fn resolve_event_opt(&self, addr: &AbsoluteAddr) -> Option<Self::Event>;
fn resolve_eval_only_event(&self, addr: &AbsoluteAddr) -> Option<Self::Event>;
fn resolve_apply_event(&self, addr: &AbsoluteAddr) -> Option<Self::Event>;
fn set<T: Copy>(&mut self, signal: SignalRef, val: T);
fn set_wide(&mut self, signal: SignalRef, val: BigUint);
fn set_four_state(&mut self, signal: SignalRef, val: BigUint, mask: BigUint);
fn get(&self, signal: SignalRef) -> BigUint;
fn get_as<T: Default + Copy>(&self, signal: SignalRef) -> T;
fn get_four_state(&self, signal: SignalRef) -> (BigUint, BigUint);
fn memory_as_ptr(&self) -> (*const u8, usize);
fn memory_as_mut_ptr(&mut self) -> (*mut u8, usize);
fn memory_owner(&self) -> Option<Arc<dyn Any + Send + Sync>> {
None
}
fn runtime_event_buffer_as_ptr(&self) -> (*const u8, usize);
fn runtime_event_buffer(&self) -> Option<Arc<RuntimeEventBuffer>> {
None
}
fn set_comb_capture_event_enabled(&mut self, _active_sites: &[bool]) {}
fn stable_region_size(&self) -> usize;
fn layout(&self) -> &MemoryLayout;
fn id_to_addr_slice(&self) -> &[AbsoluteAddr];
fn id_to_event_slice(&self) -> &[Self::Event];
fn num_events(&self) -> usize;
fn clear_triggered_bits(&mut self);
fn mark_triggered_bit(&mut self, id: usize);
fn get_triggered_bits(&self) -> bit_set::BitSet;
fn vcd_tracking_enabled(&self) -> bool {
false
}
fn take_vcd_activity(&mut self, groups: &mut Vec<usize>) -> bool {
groups.clear();
if !self.vcd_tracking_enabled() {
return false;
}
let Some(trace) = self.layout().trace.as_ref() else {
return false;
};
let (ptr, size) = self.memory_as_ptr();
let memory = unsafe { std::slice::from_raw_parts_mut(ptr.cast_mut(), size) };
trace.take(memory, groups);
true
}
fn mark_vcd_signal(&mut self, signal: SignalRef) {
if let Some(trace) = self.layout().trace.as_ref() {
let len = signal.array_layout.map_or_else(
|| celox_state_layout::get_byte_size(signal.width),
|array| array.plane_size,
);
let (ptr, _) = self.memory_as_ptr();
unsafe {
trace.mark_range(ptr.cast_mut(), signal.offset, len);
}
}
}
}