use crate::stdlib::AsHostedDef;
use super::*;
#[derive(Default, Debug, Clone, PartialEq, Eq)]
pub struct LabSet {
pub(crate) min_safe: Lab,
pub(crate) bits: Cow<'static, [u64]>,
}
impl LabSet {
pub const NONE: LabSet = LabSet { min_safe: 0, bits: Cow::Borrowed(&[]) };
pub const ALL: LabSet = LabSet { min_safe: Lab::MAX, bits: Cow::Borrowed(&[u64::MAX; 1024]) };
pub fn add(&mut self, lab: Lab) {
self.min_safe = self.min_safe.max(lab + 1);
let index = (lab >> 6) as usize;
let bit = lab & 63;
let bits = self.bits.to_mut();
if index >= bits.len() {
bits.resize(index + 1, 0);
}
bits[index] |= 1 << bit;
}
pub fn has(&self, lab: Lab) -> bool {
if lab >= self.min_safe {
return false;
}
let index = (lab >> 6) as usize;
let bit = lab & 63;
unsafe { self.bits.get_unchecked(index) & 1 << bit != 0 }
}
pub fn union(&mut self, other: &LabSet) {
self.min_safe = self.min_safe.max(other.min_safe);
let bits = self.bits.to_mut();
for (a, b) in bits.iter_mut().zip(other.bits.iter()) {
*a |= b;
}
if other.bits.len() > bits.len() {
bits.extend_from_slice(&other.bits[bits.len() ..])
}
}
pub const fn from_bits(bits: &'static [u64]) -> Self {
if bits.is_empty() {
return LabSet::NONE;
}
let min_safe = (bits.len() << 6) as u16 - bits[bits.len() - 1].leading_zeros() as u16;
LabSet { min_safe, bits: Cow::Borrowed(bits) }
}
}
impl FromIterator<Lab> for LabSet {
fn from_iter<T: IntoIterator<Item = Lab>>(iter: T) -> Self {
let mut set = LabSet::default();
for lab in iter {
set.add(lab);
}
set
}
}
#[repr(C)] #[repr(align(32))] pub struct Def<T: ?Sized + Send + Sync = Dynamic> {
pub labs: LabSet,
ty: TypeId,
call_strict: unsafe fn(*const Def<T>, &mut Net<Strict>, port: Port),
call_lazy: unsafe fn(*const Def<T>, &mut Net<Lazy>, port: Port),
pub data: T,
}
extern "C" {
#[doc(hidden)]
pub type Dynamic;
}
unsafe impl Send for Dynamic {}
unsafe impl Sync for Dynamic {}
pub trait AsDef: Any + Send + Sync {
unsafe fn call<M: Mode>(slf: *const Def<Self>, net: &mut Net<M>, port: Port);
}
impl<T: Send + Sync> Def<T> {
pub const fn new(labs: LabSet, data: T) -> Self
where
T: AsDef,
{
Def { labs, ty: TypeId::of::<T>(), call_strict: T::call::<Strict>, call_lazy: T::call::<Lazy>, data }
}
#[inline(always)]
pub const fn upcast(&self) -> &Def {
unsafe { &*(self as *const _ as *const _) }
}
#[inline(always)]
pub fn upcast_mut(&mut self) -> &mut Def {
unsafe { &mut *(self as *mut _ as *mut _) }
}
}
impl Def {
#[inline(always)]
pub unsafe fn downcast_ptr<T: Send + Sync + 'static>(slf: *const Def) -> Option<*const Def<T>> {
if (*slf).ty == TypeId::of::<T>() { Some(slf.cast()) } else { None }
}
#[inline(always)]
pub unsafe fn downcast_mut_ptr<T: Send + Sync + 'static>(slf: *mut Def) -> Option<*mut Def<T>> {
if (*slf).ty == TypeId::of::<T>() { Some(slf.cast()) } else { None }
}
#[inline(always)]
pub fn downcast_ref<T: Send + Sync + 'static>(&self) -> Option<&Def<T>> {
unsafe { Def::downcast_ptr(self).map(|x| &*x) }
}
#[inline(always)]
pub fn downcast_mut<T: Send + Sync + 'static>(&mut self) -> Option<&mut Def<T>> {
unsafe { Def::downcast_mut_ptr(self).map(|x| &mut *x) }
}
#[inline(always)]
pub unsafe fn call<M: Mode>(slf: *const Def, net: &mut Net<M>, port: Port) {
match net.as_dyn_mut() {
DynNetMut::Strict(net) => ((*slf).call_strict)(slf as *const _, net, port),
DynNetMut::Lazy(net) => ((*slf).call_lazy)(slf as *const _, net, port),
}
}
}
impl<T: Send + Sync> Deref for Def<T> {
type Target = Def;
#[inline(always)]
fn deref(&self) -> &Self::Target {
self.upcast()
}
}
impl<T: Send + Sync> DerefMut for Def<T> {
#[inline(always)]
fn deref_mut(&mut self) -> &mut Self::Target {
self.upcast_mut()
}
}
impl<F: Fn(&mut Net<Strict>, Port) + Send + Sync + 'static, G: Fn(&mut Net<Lazy>, Port) + Send + Sync + 'static> AsDef
for (F, G)
{
unsafe fn call<M: Mode>(slf: *const Def<Self>, net: &mut Net<M>, port: Port) {
match net.as_dyn_mut() {
DynNetMut::Strict(net) => ((*slf).data.0)(net, port),
DynNetMut::Lazy(net) => ((*slf).data.1)(net, port),
}
}
}
impl<'a, M: Mode> Net<'a, M> {
#[inline(never)]
pub fn call(&mut self, port: Port, trg: Port) {
trace!(self, port, trg);
let def = port.addr().def();
if trg.tag() == Ctr && !def.labs.has(trg.lab()) {
return self.comm02(port, trg);
}
self.rwts.dref += 1;
unsafe { Def::call(port.addr().0 as *const _, self, trg) }
}
}
#[derive(Debug, Default, Clone)]
pub struct InterpretedDef {
pub(crate) instr: Vec<Instruction>,
pub(crate) trgs: usize,
}
impl AsHostedDef for InterpretedDef {
fn call<M: Mode>(def: &Def<InterpretedDef>, net: &mut Net<M>, trg: Port) {
let def = &def.data;
let instructions = &def.instr;
if def.trgs >= net.trgs.len() {
net.trgs = Box::new_uninit_slice(def.trgs);
}
let mut trgs = Trgs(&mut net.trgs[..] as *mut _ as *mut _);
struct Trgs(*mut Trg);
impl Trgs {
#[inline(always)]
fn get_trg(&self, i: TrgId) -> Trg {
unsafe { (*self.0.byte_offset(i.byte_offset as _)).clone() }
}
#[inline(always)]
fn set_trg(&mut self, i: TrgId, trg: Trg) {
unsafe { *self.0.byte_offset(i.byte_offset as _) = trg }
}
}
trgs.set_trg(TrgId::new(0), Trg::port(trg));
for i in instructions {
unsafe {
match *i {
Instruction::Const { trg, ref port } => trgs.set_trg(trg, Trg::port(port.clone())),
Instruction::Link { a, b } => net.link_trg(trgs.get_trg(a), trgs.get_trg(b)),
Instruction::LinkConst { trg, ref port } => {
if !port.is_principal() {
unreachable_unchecked()
}
net.link_trg_port(trgs.get_trg(trg), port.clone())
}
Instruction::Ctr { lab, trg, lft, rgt } => {
let (l, r) = net.do_ctr(lab, trgs.get_trg(trg));
trgs.set_trg(lft, l);
trgs.set_trg(rgt, r);
}
Instruction::Op { op, trg, rhs, out } => {
let (r, o) = net.do_op(op, trgs.get_trg(trg));
trgs.set_trg(rhs, r);
trgs.set_trg(out, o);
}
Instruction::OpNum { op, trg, ref rhs, out } => {
let o = net.do_op_num(op, trgs.get_trg(trg), rhs.clone());
trgs.set_trg(out, o);
}
Instruction::Mat { trg, lft, rgt } => {
let (l, r) = net.do_mat(trgs.get_trg(trg));
trgs.set_trg(lft, l);
trgs.set_trg(rgt, r);
}
Instruction::Wires { av, aw, bv, bw } => {
let (avt, awt, bvt, bwt) = net.do_wires();
trgs.set_trg(av, avt);
trgs.set_trg(aw, awt);
trgs.set_trg(bv, bvt);
trgs.set_trg(bw, bwt);
}
}
}
}
}
}