1use hdl_cat_circuit::{CircuitArrow, CircuitTensor, Obj};
4use hdl_cat_error::Error;
5use hdl_cat_ir::{BinOp, HdlGraphBuilder, Op, WireTy};
6
7pub type HalfAdderArrow = CircuitArrow<
10 CircuitTensor<Obj<bool>, Obj<bool>>,
11 CircuitTensor<Obj<bool>, Obj<bool>>,
12>;
13
14pub type FullAdderArrow = CircuitArrow<
18 CircuitTensor<CircuitTensor<Obj<bool>, Obj<bool>>, Obj<bool>>,
19 CircuitTensor<Obj<bool>, Obj<bool>>,
20>;
21
22pub fn half_adder() -> Result<HalfAdderArrow, Error> {
32 let (bld, a) = HdlGraphBuilder::new().with_wire(WireTy::Bit);
33 let (bld, b) = bld.with_wire(WireTy::Bit);
34 let (bld, sum) = bld.with_wire(WireTy::Bit);
35 let (bld, carry) = bld.with_wire(WireTy::Bit);
36 let bld = bld.with_instruction(Op::Bin(BinOp::Xor), vec![a, b], sum)?;
37 let bld = bld.with_instruction(Op::Bin(BinOp::And), vec![a, b], carry)?;
38 Ok(CircuitArrow::from_raw_parts(
39 bld.build(),
40 vec![a, b],
41 vec![sum, carry],
42 ))
43}
44
45pub fn full_adder() -> Result<FullAdderArrow, Error> {
55 let (bld, a) = HdlGraphBuilder::new().with_wire(WireTy::Bit);
56 let (bld, b) = bld.with_wire(WireTy::Bit);
57 let (bld, cin) = bld.with_wire(WireTy::Bit);
58 let (bld, ab) = bld.with_wire(WireTy::Bit); let (bld, ab_and) = bld.with_wire(WireTy::Bit); let (bld, c_and) = bld.with_wire(WireTy::Bit); let (bld, sum) = bld.with_wire(WireTy::Bit); let (bld, cout) = bld.with_wire(WireTy::Bit); let bld = bld.with_instruction(Op::Bin(BinOp::Xor), vec![a, b], ab)?;
64 let bld = bld.with_instruction(Op::Bin(BinOp::And), vec![a, b], ab_and)?;
65 let bld = bld.with_instruction(Op::Bin(BinOp::And), vec![cin, ab], c_and)?;
66 let bld = bld.with_instruction(Op::Bin(BinOp::Xor), vec![ab, cin], sum)?;
67 let bld = bld.with_instruction(Op::Bin(BinOp::Or), vec![ab_and, c_and], cout)?;
68 Ok(CircuitArrow::from_raw_parts(
69 bld.build(),
70 vec![a, b, cin],
71 vec![sum, cout],
72 ))
73}
74
75#[cfg(test)]
76mod tests {
77 use super::{full_adder, half_adder};
78
79 #[test]
80 fn half_adder_builds() -> Result<(), hdl_cat_error::Error> {
81 let ha = half_adder()?;
82 assert_eq!(ha.inputs().len(), 2);
83 assert_eq!(ha.outputs().len(), 2);
84 assert_eq!(ha.graph().instructions().len(), 2);
85 Ok(())
86 }
87
88 #[test]
89 fn half_adder_sum_and_carry_exist() -> Result<(), hdl_cat_error::Error> {
90 let ha = half_adder()?;
91 assert_eq!(ha.graph().wires().len(), 4);
92 Ok(())
93 }
94
95 #[test]
96 fn full_adder_builds() -> Result<(), hdl_cat_error::Error> {
97 let fa = full_adder()?;
98 assert_eq!(fa.inputs().len(), 3);
99 assert_eq!(fa.outputs().len(), 2);
100 assert_eq!(fa.graph().instructions().len(), 5);
101 Ok(())
102 }
103}