use std::ops::Deref;
use crate::{Aig, AigEdge, AigError, AigNode, Result};
impl Aig {
pub fn deep_clone(&self) -> Result<Self> {
self.check_integrity()?;
let mut aig = Aig::new();
let node_false = aig.get_node(0).unwrap();
for input in &self.get_inputs() {
if let AigNode::Input(id) = input.borrow().deref() {
aig.add_node(AigNode::Input(*id))?;
} else {
panic!("Expected input, got node {:?}", input);
}
}
for latch in self.get_latches() {
if let AigNode::Latch { id, init, .. } = latch.borrow().deref() {
aig.add_node(AigNode::Latch {
id: *id,
next: AigEdge::new(node_false.clone(), false),
init: *init,
})?;
} else {
panic!("Expected latch, got node {:?}", latch);
}
}
for node in self.get_topological_sort()? {
if let AigNode::And {
id, fanin0, fanin1, ..
} = node.borrow().deref()
{
let i0 = fanin0.get_node().borrow().get_id();
let new_fanin0 = AigEdge::new(
aig.get_node(i0).ok_or(AigError::NodeDoesNotExist(i0))?,
fanin0.get_complement(),
);
let i1 = fanin1.get_node().borrow().get_id();
let new_fanin1 = AigEdge::new(
aig.get_node(i1).ok_or(AigError::NodeDoesNotExist(i1))?,
fanin1.get_complement(),
);
aig.add_node(AigNode::and(*id, new_fanin0, new_fanin1))?;
}
}
for id in aig.get_latches_id() {
let latch_ref = self.get_node(id).ok_or(AigError::NodeDoesNotExist(id))?;
if let AigNode::Latch { next, .. } = latch_ref.borrow().deref() {
aig.replace_fanin(
id,
crate::FaninId::Fanin0,
next.get_node().borrow().get_id(),
next.complement,
)?;
} else {
panic!("Expected latch, got node {:?}", latch_ref);
}
}
for output in self.get_outputs() {
aig.add_output(output.get_node().borrow().get_id(), output.complement)?;
}
aig.update();
aig.check_integrity()?;
Ok(aig)
}
}
#[cfg(test)]
mod test {
use std::path::Path;
use crate::Aig;
fn deep_clone_test<P: AsRef<Path>>(path: P) {
let aig = Aig::from_file(path).unwrap();
let new = aig.deep_clone().unwrap();
assert_eq!(aig, new);
}
#[test]
fn deep_clone_half_adder() {
deep_clone_test("assets/circuits/half-adder.aag");
}
#[test]
fn deep_clone_ctrl() {
deep_clone_test("assets/circuits/ctrl.aig");
}
#[test]
fn deep_clone_beemandrsn1f1() {
deep_clone_test("assets/circuits/beemandrsn1f1.aig");
}
}