mod fault;
mod incremental_sim;
mod simple_sim;
use crate::sim::incremental_sim::IncrementalSimulator;
use crate::Network;
pub use fault::Fault;
fn bool_to_multi(values: &Vec<Vec<bool>>) -> Vec<Vec<u64>> {
let mut ret = Vec::<Vec<u64>>::new();
for v in values {
ret.push(v.iter().map(|b| if *b { !0 } else { 0 }).collect());
}
ret
}
fn multi_to_bool(values: &Vec<Vec<u64>>) -> Vec<Vec<bool>> {
let mut ret = Vec::new();
for v in values {
ret.push(v.iter().map(|b| *b != 0).collect());
}
ret
}
pub fn simulate(a: &Network, input_values: &Vec<Vec<bool>>) -> Vec<Vec<bool>> {
let multi_input = bool_to_multi(input_values);
let multi_ret = simulate_multi(a, &multi_input);
multi_to_bool(&multi_ret)
}
pub fn simulate_comb(a: &Network, input_values: &Vec<bool>) -> Vec<bool> {
assert!(a.is_comb());
let input = vec![input_values.clone()];
let output = simulate(a, &input);
output[0].clone()
}
pub fn simulate_with_faults(
a: &Network,
input_values: &Vec<Vec<bool>>,
faults: &Vec<Fault>,
) -> Vec<Vec<bool>> {
let multi_input = bool_to_multi(input_values);
let multi_ret = simulate_multi_with_faults(a, &multi_input, faults);
multi_to_bool(&multi_ret)
}
pub fn simulate_comb_with_faults(
a: &Network,
input_values: &Vec<bool>,
faults: &Vec<Fault>,
) -> Vec<bool> {
assert!(a.is_comb());
let input = vec![input_values.clone()];
let output = simulate_with_faults(a, &input, faults);
output[0].clone()
}
pub(crate) fn simulate_multi(a: &Network, input_values: &Vec<Vec<u64>>) -> Vec<Vec<u64>> {
use simple_sim::SimpleSimulator;
let mut sim = SimpleSimulator::from_aig(a);
sim.run(input_values)
}
pub(crate) fn simulate_multi_with_faults(
a: &Network,
input_values: &Vec<Vec<u64>>,
faults: &Vec<Fault>,
) -> Vec<Vec<u64>> {
use simple_sim::SimpleSimulator;
let mut sim = SimpleSimulator::from_aig(a);
sim.run_with_faults(input_values, faults)
}
pub(crate) fn detects_faults_multi(
aig: &Network,
pattern: &Vec<u64>,
faults: &Vec<Fault>,
) -> Vec<u64> {
assert!(aig.is_comb());
assert!(aig.is_topo_sorted());
let mut incr_sim = IncrementalSimulator::from_aig(aig);
incr_sim.run_initial(pattern);
let mut detections = Vec::new();
for f in faults {
detections.push(incr_sim.detects_fault(*f));
}
detections
}
pub(crate) fn detects_faults(aig: &Network, pattern: &Vec<bool>, faults: &Vec<Fault>) -> Vec<bool> {
let multi_pattern = pattern
.iter()
.map(|b| if *b { !0u64 } else { 0u64 })
.collect();
let detections = detects_faults_multi(aig, &multi_pattern, faults);
detections
.iter()
.map(|d| {
debug_assert!(*d == 0u64 || *d == !0u64);
*d != 0
})
.collect()
}
#[cfg(test)]
mod tests {
use crate::network::NaryType;
use crate::{Gate, Network};
use super::simulate;
#[test]
fn test_basic() {
let mut aig = Network::default();
let i0 = aig.add_input();
let i1 = aig.add_input();
let i2 = aig.add_input();
let x1 = aig.xor(i0, i1);
let x2 = aig.and(i0, i2);
let x3 = aig.and(x2, !i1);
aig.add_output(x1);
aig.add_output(x3);
assert_eq!(
simulate(&aig, &vec![vec![false, false, false]]),
vec![vec![false, false]]
);
assert_eq!(
simulate(&aig, &vec![vec![true, false, false]]),
vec![vec![true, false]]
);
assert_eq!(
simulate(&aig, &vec![vec![true, false, true]]),
vec![vec![true, true]]
);
assert_eq!(
simulate(&aig, &vec![vec![true, true, true]]),
vec![vec![false, false]]
);
}
#[test]
fn test_dff() {
let mut aig = Network::default();
let d = aig.add_input();
let en = aig.add_input();
let res = aig.add_input();
let x = aig.dff(d, en, res);
aig.add_output(x);
let pattern = vec![
vec![false, false, false],
vec![false, true, false],
vec![true, true, false],
vec![true, false, false],
vec![true, false, true],
vec![false, false, false],
];
let expected = vec![
vec![false],
vec![false],
vec![false],
vec![true],
vec![true],
vec![false],
];
assert_eq!(simulate(&aig, &pattern), expected);
}
#[test]
fn test_nary() {
let mut aig = Network::default();
let i0 = aig.add_input();
let i1 = aig.add_input();
let i2 = aig.add_input();
let i3 = aig.add_input();
let x0 = aig.add(Gate::Nary(Box::new([i0, i1, i2, i3]), NaryType::And));
aig.add_output(x0);
let x1 = aig.add(Gate::Nary(Box::new([i0, i1, i2, i3]), NaryType::Xor));
aig.add_output(x1);
let x2 = aig.add(Gate::Nary(Box::new([i0, i1, i2, i3]), NaryType::Or));
aig.add_output(x2);
let x3 = aig.add(Gate::Nary(Box::new([i0, i1, i2, i3]), NaryType::Nand));
aig.add_output(x3);
let x4 = aig.add(Gate::Nary(Box::new([i0, i1, i2, i3]), NaryType::Nor));
aig.add_output(x4);
let x5 = aig.add(Gate::Nary(Box::new([i0, i1, i2, i3]), NaryType::Xnor));
aig.add_output(x5);
let pattern = vec![
vec![false, false, false, false],
vec![true, false, false, false],
vec![false, true, false, false],
vec![false, false, true, false],
vec![false, false, false, true],
vec![true, true, true, true],
];
let expected = vec![
vec![false, false, false, true, true, true],
vec![false, true, true, true, false, false],
vec![false, true, true, true, false, false],
vec![false, true, true, true, false, false],
vec![false, true, true, true, false, false],
vec![true, false, true, false, false, true],
];
assert_eq!(simulate(&aig, &pattern), expected);
}
}