1use crate::{
8 helpers::sort2,
9 network::*,
10 networks::generic_network::*,
11 truth_table::small_lut::{truth_table_library, SmallTruthTable},
12};
13
14use super::SimplifyResult;
15
16pub type Aig = LogicNetwork<AigNode>;
37
38pub type AigNodeId = NodeId;
40
41#[derive(Clone, Copy, Debug, Hash, PartialEq, PartialOrd, Eq, Ord)]
43pub struct AigNode {
44 pub(super) a: AigNodeId,
45 pub(super) b: AigNodeId,
46 num_references: usize,
48}
49
50impl AigNode {
51 fn new([a, b]: [AigNodeId; 2]) -> Self {
53 Self {
54 a,
55 b,
56 num_references: 0,
57 }
58 }
59
60 fn to_array(self) -> [AigNodeId; 2] {
62 [self.a, self.b]
63 }
64
65 fn to_array_mut(&mut self) -> [&mut AigNodeId; 2] {
67 [&mut self.a, &mut self.b]
68 }
69}
70
71impl NetworkNode for AigNode {
72 type NodeId = AigNodeId;
73
74 fn num_inputs(&self) -> usize {
75 2
76 }
77
78 fn get_input(&self, i: usize) -> Self::NodeId {
79 match i {
80 0 => self.a,
81 1 => self.b,
82 _ => panic!("index out of bounds"),
83 }
84 }
85
86 fn function(&self) -> SmallTruthTable {
87 truth_table_library::and2()
88 }
89
90 fn normalized(self) -> SimplifyResult<Self, Self::NodeId> {
91 Aig::simplify_node(self)
92 }
93}
94
95impl MutNetworkNode for AigNode {
96 fn set_input(&mut self, i: usize, signal: Self::NodeId) {
97 let input = match i {
98 0 => &mut self.a,
99 1 => &mut self.b,
100 _ => panic!("index out of bounds"),
101 };
102
103 *input = signal;
104 }
105}
106
107impl NetworkNodeWithReferenceCount for AigNode {
108 fn num_references(&self) -> usize {
109 self.num_references
110 }
111}
112
113impl MutNetworkNodeWithReferenceCount for AigNode {
114 fn reference(&mut self) {
115 self.num_references += 1;
116 }
117
118 fn dereference(&mut self) {
119 self.num_references -= 1;
120 }
121}
122
123impl IntoIterator for AigNode {
124 type Item = AigNodeId;
125
126 type IntoIter = std::array::IntoIter<AigNodeId, 2>;
127
128 fn into_iter(self) -> Self::IntoIter {
129 debug_assert_eq!(
131 self.to_array(),
132 sort2(self.to_array()),
133 "inputs must be sorted"
134 );
135
136 self.to_array().into_iter()
137 }
138}
139
140impl Aig {
141 fn simplify_node(node: AigNode) -> SimplifyResult<AigNode, NodeId> {
146 SimplifyResult::new_node(node)
147 .and_then(Self::simplify_node_by_majority)
149 .and_then(Self::simplify_constants)
150 .map_unsimplified(Self::normalize_node_by_commutativity) }
152
153 fn normalize_node_by_commutativity(node: AigNode) -> AigNode {
156 let [a, b] = sort2(node.to_array());
157 AigNode { a, b, ..node }
158 }
159
160 fn simplify_node_by_majority(node: AigNode) -> SimplifyResult<AigNode, NodeId> {
162 let [a, b] = [node.a, node.b];
163 match [a, b] {
164 [x, y] if x == y => SimplifyResult::new_id(x),
166 [x, y] if x == y.invert() => SimplifyResult::new_id(AigNodeId::zero()),
168 _ => SimplifyResult::new_node(node),
169 }
170 }
171
172 fn simplify_constants(node: AigNode) -> SimplifyResult<AigNode, NodeId> {
174 let [a, b] = node.to_array();
175 match [a, b] {
176 [x, _] | [_, x] if x.is_zero() => SimplifyResult::new_id(AigNodeId::zero()),
177 [x, y] | [y, x] if x.is_one() => SimplifyResult::new_id(y),
178 _ => SimplifyResult::new_node(node),
179 }
180 }
181}
182
183impl HomogeneousNetwork for Aig {
184 const NUM_NODE_INPUTS: usize = 2;
185
186 fn function(&self) -> Self::NodeFunction {
187 crate::truth_table::small_lut::truth_table_library::and2()
188 }
189}
190
191impl SubstituteInNode for Aig {
192 fn substitute_in_node(
193 &mut self,
194 node: Self::NodeId,
195 old_signal: Self::Signal,
196 new_signal: Self::Signal,
197 ) {
198 if let Some(n) = self.get_logic_node_mut(node) {
199 n.to_array_mut()
201 .into_iter()
202 .filter(|input| **input == old_signal)
203 .for_each(|input| *input = new_signal);
204 }
205 }
206}
207
208impl UnaryOp for Aig {
209 fn create_not(&mut self, signal: Self::Signal) -> Self::Signal {
210 signal.invert()
211 }
212}
213
214impl BinaryOp for Aig {
215 fn create_and(&mut self, a: Self::Signal, b: Self::Signal) -> Self::Signal {
216 let node = AigNode::new([a, b]);
217 match Self::simplify_node(node) {
219 SimplifyResult::Node(n, invert) => self.create_node(n).invert_if(invert),
220 SimplifyResult::Simplified(s, invert) => s.invert_if(invert),
221 }
222 }
223
224 fn create_or(&mut self, a: Self::Signal, b: Self::Signal) -> Self::Signal {
225 self.create_and(a.invert(), b.invert()).invert()
226 }
227
228 fn create_nand(&mut self, a: Self::Signal, b: Self::Signal) -> Self::Signal {
229 self.create_and(a, b).invert()
230 }
231
232 fn create_nor(&mut self, a: Self::Signal, b: Self::Signal) -> Self::Signal {
233 self.create_or(a, b).invert()
234 }
235
236 fn create_xor(&mut self, a: Self::Signal, b: Self::Signal) -> Self::Signal {
237 let x = self.create_and(a, b.invert());
238 let y = self.create_and(a.invert(), b);
239 self.create_or(x, y)
240 }
241}
242
243impl TernaryOp for Aig {}
244
245#[test]
246fn test_aig_create_constants() {
247 let aig = Aig::new();
248
249 let zero = aig.get_constant(false);
250 let one = aig.get_constant(true);
251
252 assert!(zero.is_constant());
253 assert!(one.is_constant());
254
255 assert!(zero.is_zero());
256
257 assert_ne!(zero, one);
258 assert_eq!(zero.invert(), one);
259}
260
261#[test]
262fn test_aig_create_primary_inputs() {
263 let mut aig = Aig::new();
264 let a = aig.create_primary_input();
265 let b = aig.create_primary_input();
266 let c = aig.create_primary_input();
267
268 assert_ne!(a, b);
269 assert_ne!(b, c);
270
271 assert!(aig.is_input(a));
272 assert!(aig.is_input(b));
273 assert!(aig.is_input(c));
274
275 assert!(!aig.is_constant(a));
276}
277
278#[test]
279fn test_aig_node_deduplication() {
280 let mut aig = Aig::new();
281
282 let a = aig.create_primary_input();
283 let b = aig.create_primary_input();
284
285 let a_and_b_1 = aig.create_and(a, b);
286 let a_and_b_2 = aig.create_and(a, b);
287
288 assert_eq!(a_and_b_1, a_and_b_2);
289}
290
291#[test]
292fn test_aig_node_simplification_by_commutativity() {
293 let mut aig = Aig::new();
294
295 let a = aig.create_primary_input();
296 let b = aig.create_primary_input();
297
298 let a_and_b_1 = aig.create_and(a, b);
299 let a_and_b_2 = aig.create_and(b, a);
300
301 assert_eq!(a_and_b_1, a_and_b_2);
302}
303
304#[test]
305fn test_aig_node_simplification_by_majority() {
306 let mut aig = Aig::new();
307
308 let a = aig.create_primary_input();
309
310 let a_and_a = aig.create_and(a, a);
311 assert_eq!(a_and_a, a);
312}
313
314#[test]
315fn test_aig_node_simplification_with_constants() {
316 let mut aig = Aig::new();
317
318 let a = aig.create_primary_input();
319
320 let zero = aig.get_constant(false);
321
322 let a_and_zero = aig.create_and(a, zero);
323
324 assert_eq!(a_and_zero, zero);
325}
326
327#[test]
328fn test_aig_simulation() {
329 use crate::native_boolean_functions::NativeBooleanFunction;
330 use crate::traits::BooleanSystem;
331
332 let mut aig = Aig::new();
334 let [in1, in2, carry_in] = aig.create_primary_inputs();
335
336 let sum = aig.create_xor3(in1, in2, carry_in);
337 let carry = aig.create_maj3(in1, in2, carry_in);
338
339 let output_sum = aig.create_primary_output(sum);
340 let output_carry = aig.create_primary_output(carry);
341
342 let simulator = crate::network_simulator::RecursiveSim::new(&aig);
343
344 fn full_adder([a, b, c]: [bool; 3]) -> [bool; 2] {
346 let sum = (a as usize) + (b as usize) + (c as usize);
347 [
348 sum & 0b1 == 1,
349 sum & 0b10 == 0b10, ]
351 }
352
353 let reference = NativeBooleanFunction::new(full_adder);
354
355 for i in 0..(1 << 3) {
356 let inputs = [0, 1, 2].map(|idx| (i >> idx) & 1 == 1);
357
358 let exptected_output = [0, 1].map(|out| reference.evaluate_term(&out, &inputs));
359 let actual_output: Vec<_> = simulator
360 .simulate(&[output_sum, output_carry], &inputs)
361 .collect();
362
363 dbg!(inputs);
364
365 assert_eq!(exptected_output.as_slice(), actual_output.as_slice());
366 }
367}