logic-circus 0.3.0

Open source logic circuit simualtor written in Rust.
Documentation
use crate::{Bit, Gate, GateLike, Sequal};

pub(super) trait SequalsExtension<Rust> {
    unsafe fn run(
        &self,
        for_gate: usize,
        output: &[Bit],
        gates: &mut [Gate<Rust>],
        outputs: &mut [Bit],
    );
}

impl<Rust> SequalsExtension<Rust> for [Vec<Sequal>]
where
    Rust: GateLike,
{
    /// # Safety
    /// this function is only safe if:
    /// - the index of the gate in `for_gate` is in bounds for (`self`)
    /// - the amount of sequals in `self[for_gate]` is equal to the amount of
    ///   `output`s received from the last gate
    /// - all `Sequal::End`s point to outputs that exist - guaranteed if
    ///   constructed with [`ComponentBuilder`] and used outputs from 0 up to
    ///   the number of outputs
    /// - all `Sequal::Gate`s must point to actual inputs of actual gates
    /// - component is clean (right after construction or after a call to
    ///   `Component::reset()`)
    unsafe fn run(
        &self,
        for_gate: usize,
        output: &[Bit],
        gates: &mut [Gate<Rust>],
        outputs: &mut [Bit],
    ) {
        debug_assert!(
            for_gate < self.len(),
            "this gate (index: {}) doesn't have documented sequals",
            for_gate
        );
        let sequals = unsafe { self.get_unchecked(for_gate) };

        debug_assert_eq!(
            sequals.len(),
            output.len(),
            "not every output bit has a matching sequal (gate index: {})",
            for_gate
        );
        for (sequal, data) in sequals.iter().copied().zip(output.iter().copied()) {
            match sequal {
                Sequal::End { output } => {
                    debug_assert!(
                        output < outputs.len(),
                        "this component output is out of bounds (in sequal of gate {})",
                        for_gate
                    );
                    // this blocks having one less vectors because the index in
                    // `output` isn't necessarily the same as the index of data
                    // in output
                    *unsafe { outputs.get_unchecked_mut(output) } = data;
                }
                Sequal::Gate { index, entry } => {
                    if let Some(output) = unsafe {
                        debug_assert!(index < gates.len());
                        unsafe { gates.get_unchecked_mut(index) }.fill_input(data, entry)
                    } {
                        self.run(index, &output, gates, outputs);
                        drop(output); // just want to emphasize this is where deallocation happens for Gate.inputs
                    }
                }
            }
        }
    }
}