1use prjunnamed_netlist::{Cell, CellRef, ControlNet, Design, FlipFlop, IoBuffer, Net, ParamValue, Trit, Value};
2use prjunnamed_pattern::{netlist_replace, patterns::*};
3
4pub fn simplify(design: &mut Design) -> bool {
5 let rules = netlist_replace! {
6 [PBuf [PAny@a]] => a;
7
8 [PNot [PConst@a]] => a.not();
9 [PNot [PNot [PAny@a]]] => a;
10
11 [PAnd [PConst@a] [PConst@b]] => a.and(b);
12 [PAnd [PAny@a] [POnes]] => a;
13 [PAnd [POnes] [PAny@a]] => a;
14 [PAnd [PAny@a] [PZero]] => Value::zero(a.len());
15 [PAnd [PZero] [PAny@a]] => Value::zero(a.len());
16
17 [POr [PConst@a] [PConst@b]] => a.or(b);
18 [POr [PAny@a] [PZero]] => a;
19 [POr [PZero] [PAny@a]] => a;
20 [POr [PAny@a] [POnes]] => Value::ones(a.len());
21 [POr [POnes] [PAny@a]] => Value::ones(a.len());
22
23 [PXor [PConst@a] [PConst@b]] => a.xor(b);
24 [PXor [PAny@a] [PZero]] => a;
25 [PXor [PZero] [PAny@a]] => a;
26 [PXor [PAny@a] [POnes]] => design.add_not(a);
27 [PXor [POnes] [PAny@a]] => design.add_not(a);
28 [PXor [PAny@a] [PUndef]] => Value::undef(a.len());
29 [PXor [PUndef] [PAny@a]] => Value::undef(a.len());
30 [PXor [PAny@a] [PAny@b]] if a == b => Value::zero(a.len());
31
32 [PAnd [PAny@a] [PNot [PAny@b]]] if a == b => Value::zero(a.len());
33 [PAnd [PNot [PAny@a]] [PAny@b]] if a == b => Value::zero(a.len());
34 [POr [PAny@a] [PNot [PAny@b]]] if a == b => Value::ones(a.len());
35 [POr [PNot [PAny@a]] [PAny@b]] if a == b => Value::ones(a.len());
36 [PXor [PAny@a] [PNot [PAny@b]]] if a == b => Value::ones(a.len());
37 [PXor [PNot [PAny@a]] [PAny@b]] if a == b => Value::ones(a.len());
38
39 [PMux [POnes] [PAny@a] [PAny]] => a;
40 [PMux [PZero] [PAny] [PAny@b]] => b;
41 [PMux [PAny] [PAny@a] [PUndef]] => a;
42 [PMux [PAny] [PUndef] [PAny@b]] => b;
43 [PMux [PAny] [PAny@a] [PAny@b]] if a == b => a;
44
45 [PMux@y [PAny@s] [POnes] [PZero]] => Value::from(s).sext(y.len());
46 [PMux@y [PAny@s] [PZero] [POnes]] => design.add_not(s).sext(y.len());
47
48 [PAnd [PNot [PAny@a]] [PNot [PAny@b]]] => design.add_not(design.add_or (a, b));
49 [POr [PNot [PAny@a]] [PNot [PAny@b]]] => design.add_not(design.add_and(a, b));
50
51 [PXor [PNot [PAny@a]] [PNot [PAny@b]]] => design.add_xor(a, b);
52 [PXor [PNot [PAny@a]] [PAny@b]] => design.add_not(design.add_xor(a, b));
53 [PXor [PAny@a] [PNot [PAny@b]]] => design.add_not(design.add_xor(a, b));
54
55 [PMux [PNot [PAny@s]] [PAny@a] [PAny@b]] => design.add_mux(s, b, a);
56
57 [PAdc [PConst@a] [PConst@b] [PConst@c]] => a.adc(b, c);
58 [PAdc@y [PAny@a] [PZero] [PZero]] => a.zext(y.len());
59 [PAdc@y [PZero] [PAny@b] [PZero]] => b.zext(y.len());
60 [PAdc@y [PZero] [PZero] [PAny@c]] => Value::from(c).zext(y.len());
61
62 [PAdc [PAny@a] [PAny@b] [PAny@c]] if let Some(y) = adc_split(design, a, b, c) => y;
63 [PAdc [PAny@a] [PAny@b] [PAny@c]] if let Some(y) = adc_unsext(design, a, b, c) => y;
64
65 [PAdc@y [PAdc [PAny@a] [PAny@b] [PZero]] [PZExt [PAny@c]] [PZero]] if c.len() == 1 =>
66 design.add_adc(a, b, c[0]).zext(y.len());
67
68 [PEq [PConst@a] [PConst@b]] => a.eq(b);
69 [PEq [PAny@a] [POnes]] if a.len() == 1 => a;
70 [PEq [POnes] [PAny@a]] if a.len() == 1 => a;
71 [PEq [PAny@a] [PZero]] if a.len() == 1 => design.add_not(a);
72 [PEq [PZero] [PAny@a]] if a.len() == 1 => design.add_not(a);
73 [PEq [PAny@a] [PAny@b]] if a == b => Trit::One;
74
75 [PULt [PConst@a] [PConst@b]] => a.ult(b);
76 [PULt [PAny] [PZero]] => Trit::Zero;
77 [PULt [POnes] [PAny]] => Trit::Zero;
78 [PULt [PHasX] [PAny]] => Trit::Undef;
79 [PULt [PAny] [PHasX]] => Trit::Undef;
80 [PULt [PAny@a] [PAny@b]] if a == b => Trit::Zero;
81
82 [PSLt [PConst@a] [PConst@b]] => a.slt(b);
83 [PSLt [PHasX] [PAny]] => Trit::Undef;
84 [PSLt [PAny] [PHasX]] => Trit::Undef;
85 [PSLt [PAny@a] [PAny@b]] if a == b => Trit::Zero;
86
87 [PShl [PAny@a] [PConst@b] [PAny@s]] => a.shl(b, s);
88 [PShl [PAny@a] [PAny] [PZero]] => a;
89 [PShl@y [PZero] [PAny] [PAny]] => Value::zero(y.len());
90
91 [PUShr [PAny@a] [PConst@b] [PAny@s]] => a.ushr(b, s);
92 [PUShr [PAny@a] [PAny] [PZero]] => a;
93 [PUShr@y [PZero] [PAny] [PAny]] => Value::zero(y.len());
94
95 [PSShr [PAny@a] [PConst@b] [PAny@s]] => a.sshr(b, s);
96 [PSShr [PAny@a] [PAny] [PZero]] => a;
97 [PSShr@y [PZero] [PAny] [PAny]] => Value::zero(y.len());
98 [PSShr@y [POnes] [PAny] [PAny]] => Value::ones(y.len());
99
100 [PXShr [PAny@a] [PConst@b] [PAny@s]] => a.xshr(b, s);
101 [PXShr [PAny@a] [PAny] [PZero]] => a;
102 [PXShr@y [PZero] [PAny] [PAny]] => Value::zero(y.len());
103
104 [PMul [PConst@a] [PConst@b]] => a.mul(b);
105 [PMul@y [PAny] [PHasX]] => Value::undef(y.len());
106 [PMul@y [PHasX] [PAny]] => Value::undef(y.len());
107 [PMul@y [PAny] [PZero]] => Value::zero(y.len());
108 [PMul@y [PZero] [PAny]] => Value::zero(y.len());
109 [PMul [PAny@a] [PPow2@b]] => a.shl(Trit::One, b);
110 [PMul [PPow2@a] [PAny@b]] => b.shl(Trit::One, a);
111
112 [PUDiv@y [PZero] [PAny]] => Value::zero(y.len());
114 [PUDiv@y [PAny] [PZero]] => Value::undef(y.len());
115 [PUDiv [PAny@a] [PPow2@b]] => a.ushr(Trit::One, b);
116
117 [PUMod@y [PZero] [PAny]] => Value::zero(y.len());
119 [PUMod@y [PAny] [PZero]] => Value::undef(y.len());
120 [PUMod [PAny@a] [PPow2@b]] =>
121 if (b as usize) < a.len() { Value::from(&a[..(b as usize)]).zext(a.len()) } else { a };
122
123 [PSDivTrunc@y [PZero] [PAny]] => Value::zero(y.len());
124 [PSDivTrunc@y [PAny] [PZero]] => Value::undef(y.len());
125 [PSModTrunc@y [PZero] [PAny]] => Value::zero(y.len());
126 [PSModTrunc@y [PAny] [PZero]] => Value::undef(y.len());
127
128 [PSDivFloor@y [PZero] [PAny]] => Value::zero(y.len());
129 [PSDivFloor@y [PAny] [PZero]] => Value::undef(y.len());
130 [PSModFloor@y [PZero] [PAny]] => Value::zero(y.len());
131 [PSModFloor@y [PAny] [PZero]] => Value::undef(y.len());
132
133 [PDff@ff [PAny]] if ff.clear.is_always(true) => Value::from(ff.clear_value);
134
135 [PDff@ff [PMux [PAny@r] [PConst@rv] [PAny@d]]] if ff.reset.is_always(false) =>
136 design.add_dff(ff.clone().with_data(d).with_reset_value(ControlNet::Pos(r), rv));
137 [PDff@ff [PMux [PAny@r] [PAny@d] [PConst@rv]]] if ff.reset.is_always(false) =>
138 design.add_dff(ff.clone().with_data(d).with_reset_value(ControlNet::Neg(r), rv));
139
140 [PBind@ffq [PDff@ff [PMux [PAny@en] [PAny@d] [PAny@q]]]] if ff.enable.is_always(true) && ffq == q =>
141 design.add_dff(ff.clone().with_data(d).with_enable(ControlNet::Pos(en)));
142 [PBind@ffq [PDff@ff [PMux [PAny@en] [PAny@q] [PAny@d]]]] if ff.enable.is_always(true) && ffq == q =>
143 design.add_dff(ff.clone().with_data(d).with_enable(ControlNet::Neg(en)));
144 };
145
146 for cell_ref in design.iter_cells() {
147 fold_controls(design, cell_ref);
149 let value = cell_ref.output();
151 if rules(design, &value) {
152 continue;
153 }
154 for net in &value {
155 rules(design, &Value::from(net));
156 }
157 }
158 design.compact()
159}
160
161fn adc_split(design: &Design, a: Value, b: Value, c: Net) -> Option<Value> {
224 let mut ci = c;
225 let mut result = Value::new();
226 for (offset, (a_bit, b_bit)) in a.iter().zip(b.iter()).enumerate() {
227 if a_bit == b_bit {
232 result.extend(make_adc(design, &a[result.len()..offset], &b[result.len()..offset], ci));
233 ci = a_bit;
234 } else if offset == result.len() {
235 if a_bit == ci {
236 result.extend([b_bit]);
237 } else if b_bit == ci {
239 result.extend([a_bit]);
240 }
242 }
243 }
244 if result.is_empty() {
245 return None;
246 }
247 result.extend(make_adc(design, &a[result.len()..], &b[result.len()..], ci));
248 Some(result)
249}
250
251fn adc_unsext(design: &Design, a: Value, b: Value, c: Net) -> Option<Value> {
290 let mut ci = c;
291 let mut offset = 0;
292 let mut result = Value::new();
293 while offset + 2 < a.len() {
294 let a_bit = a[offset];
295 let b_bit = b[offset];
296 let same_count =
297 a[offset + 1..].iter().zip(&b[offset + 1..]).take_while(|&pair| pair == (&a_bit, &b_bit)).count() + 1;
298
299 if same_count < 3 {
300 offset += same_count;
301 continue;
302 }
303
304 let start_offset = result.len();
305 let end_offset = offset + same_count;
306 let chunk = make_adc(design, &a[start_offset..offset + 2], &b[start_offset..offset + 2], ci);
307 let chunk_sum = chunk.slice(..chunk.len() - 1); result.extend(chunk_sum.sext(end_offset - start_offset));
309 ci = chunk.msb();
310 offset = end_offset;
311 }
312 if result.is_empty() {
313 return None;
314 }
315 result.extend(make_adc(design, &a[result.len()..], &b[result.len()..], ci));
316 Some(result)
317}
318
319fn make_adc(design: &Design, a: impl Into<Value>, b: impl Into<Value>, ci: impl Into<Net>) -> Value {
321 let a = a.into();
322 let b = b.into();
323 let ci = ci.into();
324 if a.is_empty() {
325 assert!(b.is_empty());
326 ci.into()
327 } else {
328 design.add_adc(a, b, ci)
329 }
330}
331
332fn fold_controls(design: &Design, cell_ref: CellRef) {
333 let uninvert = |net: Net| -> Option<Net> {
334 if let Ok((cell_ref, offset)) = design.find_cell(net) {
335 if let Cell::Not(value) = &*cell_ref.get() {
336 return Some(value[offset]);
337 }
338 }
339 None
340 };
341
342 let fold_control_net = |control_net: ControlNet| {
343 if let Some(net) = uninvert(control_net.net()) {
344 if control_net.is_positive() {
345 ControlNet::Neg(net)
346 } else {
347 ControlNet::Pos(net)
348 }
349 } else {
350 control_net.canonicalize()
351 }
352 };
353
354 match &*cell_ref.get() {
355 Cell::Dff(flip_flop) => {
356 let mut flip_flop = FlipFlop {
357 clock: fold_control_net(flip_flop.clock),
358 clear: fold_control_net(flip_flop.clear),
359 reset: fold_control_net(flip_flop.reset),
360 enable: fold_control_net(flip_flop.enable),
361 ..flip_flop.clone()
362 };
363 if flip_flop.clock.is_const() {
364 flip_flop.data = Value::undef(flip_flop.data.len());
365 flip_flop.clock = ControlNet::ZERO;
366 flip_flop.reset = ControlNet::ZERO;
367 flip_flop.enable = ControlNet::ZERO;
368 }
369 if flip_flop.reset.is_always(true) {
370 flip_flop.data = flip_flop.reset_value.clone().into();
371 flip_flop.reset = ControlNet::ZERO;
372 if flip_flop.reset_over_enable {
373 flip_flop.enable = ControlNet::ONE;
374 }
375 }
376 if flip_flop.enable.is_always(false) {
377 if flip_flop.reset_over_enable {
378 flip_flop.data = flip_flop.reset_value.clone().into();
379 flip_flop.enable = flip_flop.reset;
380 flip_flop.reset = ControlNet::ZERO;
381 } else {
382 flip_flop.data = Value::undef(flip_flop.data.len());
383 flip_flop.clock = ControlNet::ZERO;
384 flip_flop.reset = ControlNet::ZERO;
385 flip_flop.enable = ControlNet::ZERO;
386 }
387 }
388 cell_ref.replace(Cell::Dff(flip_flop));
389 }
390 Cell::IoBuf(io_buffer) => {
391 cell_ref.replace(Cell::IoBuf(IoBuffer {
392 io: io_buffer.io.clone(),
393 output: io_buffer.output.clone(),
394 enable: fold_control_net(io_buffer.enable),
395 }));
396 }
397 Cell::Target(target_cell) => {
398 let mut target_cell = target_cell.clone();
399 let prototype = design.target_prototype(&target_cell);
400 for input in prototype.inputs.iter() {
401 let Some(invert_param_index) = input.invert_param else { continue };
402 let ParamValue::Const(ref mut invert_const) = target_cell.params[invert_param_index] else {
403 unreachable!()
404 };
405 for offset in input.range.clone() {
406 let const_offset = offset - input.range.start;
407 let Some(net) = uninvert(target_cell.inputs[offset]) else { continue };
408 target_cell.inputs[offset] = net;
409 invert_const[const_offset] = !invert_const[const_offset];
410 }
411 }
412 cell_ref.replace(Cell::Target(target_cell));
413 }
414 _ => (),
415 }
416}
417
418#[cfg(test)]
419mod test {
420 use std::{collections::BTreeMap, sync::Arc};
421
422 use prjunnamed_netlist::{
423 assert_isomorphic, Const, ControlNet, Design, FlipFlop, IoBuffer, Net, Target, TargetCell, TargetImportError,
424 TargetPrototype, Trit, Value,
425 };
426 use prjunnamed_pattern::{assert_netlist, netlist_match, patterns::*};
427
428 use super::simplify;
429
430 macro_rules! assert_simplify {
431 ( $( |$design:ident| $build:expr ),+ ; $( $match:tt )+ ) => {
432 let rules = netlist_match! { $( $match )+ };
433 $(
434 let mut $design = Design::new();
435 $design.add_output("y", $build);
436 $design.apply();
437 let design_before = $design.clone();
438 simplify(&mut $design);
439 assert_netlist!($design, rules, "simplify failed on:\n{}\nresult:\n{}", design_before, $design);
440 )+
441 };
442 }
443
444 macro_rules! assert_simplify_isomorphic {
445 ( $design:ident, $gold:ident ) => {
446 let (mut design, mut gold) = ($design, $gold);
447 design.apply();
448 simplify(&mut design);
449 gold.apply();
450 assert_isomorphic!(design, gold);
451 };
452 }
453
454 macro_rules! assert_no_simplify {
455 ( $design:ident ) => {
456 let mut design = $design;
457 design.apply();
458 assert!(!simplify(&mut design));
459 };
460 }
461
462 fn iter_interesting_consts() -> impl Iterator<Item = Const> {
463 ["0", "1", "X", "00", "11", "XX", "01", "10"].into_iter().map(Const::lit)
464 }
465
466 fn iter_has_undef_consts() -> impl Iterator<Item = Const> {
467 ["X", "XX", "0X", "X1"].into_iter().map(Const::lit)
468 }
469
470 fn iter_interesting_const_pairs() -> impl Iterator<Item = (Const, Const)> {
471 iter_interesting_consts().flat_map(|value1| {
472 iter_interesting_consts().filter_map(move |value2| {
473 if value1.len() == value2.len() {
474 Some((value1.clone(), value2))
475 } else {
476 None
477 }
478 })
479 })
480 }
481
482 #[allow(dead_code)]
483 #[derive(Debug)]
484 struct MockTarget {
485 prototypes: BTreeMap<String, TargetPrototype>,
486 }
487
488 impl MockTarget {
489 #[allow(dead_code)]
490 fn new() -> Arc<Self> {
491 Arc::new(MockTarget {
492 prototypes: BTreeMap::from_iter([
493 (
494 "BUF1".into(),
495 TargetPrototype::new_has_effects()
496 .add_param_bits("INVERT", Const::zero(1))
497 .add_input_invertible("I", Const::zero(1), "INVERT")
498 .add_output("O", 1),
499 ),
500 (
501 "BUF2".into(),
502 TargetPrototype::new_has_effects()
503 .add_param_bits("INVERT", Const::zero(2))
504 .add_input_invertible("I", Const::zero(2), "INVERT")
505 .add_output("O", 2),
506 ),
507 ]),
508 })
509 }
510 }
511
512 impl Target for MockTarget {
513 fn name(&self) -> &str {
514 "mock"
515 }
516
517 fn options(&self) -> BTreeMap<String, String> {
518 BTreeMap::new()
519 }
520
521 fn prototype(&self, name: &str) -> Option<&TargetPrototype> {
522 self.prototypes.get(name)
523 }
524
525 fn validate(&self, _design: &Design, _cell: &TargetCell) {}
526
527 fn import(&self, _design: &mut Design) -> Result<(), TargetImportError> {
528 Ok(())
529 }
530
531 fn export(&self, _design: &mut Design) {}
532
533 fn synthesize(&self, _design: &mut Design) -> Result<(), ()> {
534 Ok(())
535 }
536 }
537
538 #[test]
539 fn test_not_const_eval() {
540 for value in iter_interesting_consts() {
541 assert_simplify!(
542 |design| design.add_not(&value);
543 [PConst@a] => (a == value.not());
544 );
545 }
546 }
547
548 #[test]
549 fn test_not_not() {
550 assert_simplify!(
551 |ds| ds.add_not(ds.add_not(ds.add_input("a", 2)));
552 [PInput ("a")] => true;
553 );
554 }
555
556 #[test]
557 fn test_and_const_eval() {
558 for (value1, value2) in iter_interesting_const_pairs() {
559 assert_simplify!(
560 |ds| ds.add_and(&value1, &value2);
561 [PConst@a] => (a == value1.and(&value2));
562 );
563 }
564 }
565
566 #[test]
567 fn test_and_fold() {
568 for size in [1, 2] {
569 assert_simplify!(
570 |ds| ds.add_and(Const::zero(size), ds.add_input("a", size)),
571 |ds| ds.add_and(ds.add_input("a", size), Const::zero(size));
572 [PZero] => true;
573 );
574 assert_simplify!(
575 |ds| ds.add_and(Const::ones(size), ds.add_input("a", size)),
576 |ds| ds.add_and(ds.add_input("a", size), Const::ones(size));
577 [PInput ("a")] => true;
578 );
579 assert_simplify!(
580 |ds| { let a = ds.add_input("a", size); ds.add_and(&a, ds.add_not(&a)) },
581 |ds| { let a = ds.add_input("a", size); ds.add_and(ds.add_not(&a), &a) };
582 [PZero] => true;
583 );
584 }
585 }
586
587 #[test]
588 fn test_or_const_eval() {
589 for (value1, value2) in iter_interesting_const_pairs() {
590 assert_simplify!(
591 |ds| ds.add_or(&value1, &value2);
592 [PConst@a] => a == value1.or(&value2);
593 );
594 }
595 }
596
597 #[test]
598 fn test_or_fold() {
599 for size in [1, 2] {
600 assert_simplify!(
601 |ds| ds.add_or(Const::zero(size), ds.add_input("a", size)),
602 |ds| ds.add_or(ds.add_input("a", size), Const::zero(size));
603 [PInput ("a")] => true;
604 );
605 assert_simplify!(
606 |ds| ds.add_or(Const::ones(size), ds.add_input("a", size)),
607 |ds| ds.add_or(ds.add_input("a", size), Const::ones(size));
608 [POnes] => true;
609 );
610 assert_simplify!(
611 |ds| { let a = ds.add_input("a", size); ds.add_or(&a, ds.add_not(&a)) },
612 |ds| { let a = ds.add_input("a", size); ds.add_or(ds.add_not(&a), &a) };
613 [POnes] => true;
614 );
615 }
616 }
617
618 #[test]
619 fn test_xor_const_eval() {
620 for (value1, value2) in iter_interesting_const_pairs() {
621 assert_simplify!(
622 |ds| ds.add_xor(&value1, &value2);
623 [PConst@a] => a == value1.xor(&value2);
624 );
625 }
626 }
627
628 #[test]
629 fn test_xor_fold() {
630 for size in [1, 2] {
631 assert_simplify!(
632 |ds| ds.add_xor(Const::zero(size), ds.add_input("a", size)),
633 |ds| ds.add_xor(ds.add_input("a", size), Const::zero(size));
634 [PInput ("a")] => true;
635 );
636 assert_simplify!(
637 |ds| ds.add_xor(Const::ones(size), ds.add_input("a", size)),
638 |ds| ds.add_xor(ds.add_input("a", size), Const::ones(size));
639 [PNot [PInput ("a")]] => true;
640 );
641 assert_simplify!(
642 |ds| ds.add_xor(Const::undef(size), ds.add_input("a", size)),
643 |ds| ds.add_xor(ds.add_input("a", size), Const::undef(size));
644 [PUndef] => true;
645 );
646 assert_simplify!(
647 |ds| { let a = ds.add_input("a", size); ds.add_xor(&a, ds.add_not(&a)) },
648 |ds| { let a = ds.add_input("a", size); ds.add_xor(ds.add_not(&a), &a) };
649 [POnes] => true;
650 );
651 assert_simplify!(
652 |ds| {let a = ds.add_input("a", size); ds.add_xor(&a, &a)};
653 [PZero] => true;
654 );
655 }
656 }
657
658 #[test]
659 fn test_mux_fold() {
660 for size in [1, 2] {
661 assert_simplify!(
662 |ds| ds.add_mux(Net::ZERO, ds.add_input("a", size), ds.add_input("b", size));
663 [PInput ("b")] => true;
664 );
665 assert_simplify!(
666 |ds| ds.add_mux(Net::ONE, ds.add_input("a", size), ds.add_input("b", size));
667 [PInput ("a")] => true;
668 );
669 assert_simplify!(
670 |ds| ds.add_mux(ds.add_input1("s"), ds.add_input("a", size), Const::undef(size));
671 [PInput ("a")] => true;
672 );
673 assert_simplify!(
674 |ds| ds.add_mux(ds.add_input1("s"), Const::undef(size), ds.add_input("b", size));
675 [PInput ("b")] => true;
676 );
677 assert_simplify!(
678 |ds| { let a = ds.add_input("a", size); ds.add_mux(ds.add_input1("s"), &a, &a) };
679 [PInput ("a")] => true;
680 );
681 assert_simplify!(
682 |ds| ds.add_mux(ds.add_input1("s"), Const::ones(size), Const::zero(size));
683 [PSExt [PAny@s]] if s.len() == 1 => true;
684 );
685 }
686 }
687
688 #[test]
689 fn test_demorgan() {
690 for size in [1, 2] {
691 assert_simplify!(
692 |ds| ds.add_and(ds.add_not(ds.add_input("a", size)), ds.add_not(ds.add_input("b", size)));
693 [PNot [POr [PInput ("a")] [PInput ("b")]]] => true;
694 );
695 assert_simplify!(
696 |ds| ds.add_or(ds.add_not(ds.add_input("a", size)), ds.add_not(ds.add_input("b", size)));
697 [PNot [PAnd [PInput ("a")] [PInput ("b")]]] => true;
698 );
699 }
700 }
701
702 #[test]
703 fn test_xor_not_push() {
704 for size in [1, 2] {
705 assert_simplify!(
706 |ds| ds.add_xor(ds.add_not(ds.add_input("a", size)), ds.add_not(ds.add_input("b", size)));
707 [PXor [PInput ("a")] [PInput ("b")]] => true;
708 );
709 assert_simplify!(
710 |ds| ds.add_xor(ds.add_not(ds.add_input("a", size)), ds.add_input("b", size)),
711 |ds| ds.add_xor(ds.add_input("a", size), ds.add_not(ds.add_input("b", size)));
712 [PNot [PXor [PInput ("a")] [PInput ("b")]]] => true;
713 );
714 }
715 }
716
717 #[test]
718 fn test_mux_flip() {
719 for size in [1, 2] {
720 assert_simplify!(
721 |ds| ds.add_mux(ds.add_not(ds.add_input("s", 1))[0], ds.add_input("a", size), ds.add_input("b", size));
722 [PMux [PInput ("s")] [PInput ("b")] [PInput ("a")]] => true;
723 );
724 }
725 }
726
727 #[test]
728 fn test_adc_const_eval() {
729 for carry in [Trit::Zero, Trit::One, Trit::Undef] {
730 for (value1, value2) in iter_interesting_const_pairs() {
731 assert_simplify!(
732 |ds| ds.add_adc(&value1, &value2, carry);
733 [PConst@a] => a == value1.adc(&value2, carry);
734 );
735 }
736 }
737 }
738
739 #[test]
740 fn test_adc_fold() {
741 for size in [1, 2] {
742 assert_simplify!(
743 |ds| ds.add_adc(Const::zero(size), ds.add_input("a", size), Net::ZERO),
744 |ds| ds.add_adc(ds.add_input("a", size), Const::zero(size), Net::ZERO);
745 [PZExt [PInput ("a")]] => true;
746 );
747 assert_simplify!(
748 |ds| ds.add_adc(Const::zero(size), Const::zero(size), ds.add_input("c", 1)[0]);
749 [PZExt [PInput ("c")]] => true;
750 );
751 }
752 }
753
754 #[test]
755 fn test_adc_split_case1() {
756 let mut design = Design::new();
757 let a = design.add_input("a", 4);
758 let b = design.add_input("b", 4);
759 let ab = design.add_input("ab", 1);
760 let c = design.add_input("c", 1);
761 let y = design.add_adc(
762 a.slice(..2).concat(&ab).concat(a.slice(2..)),
763 b.slice(..2).concat(&ab).concat(b.slice(2..)),
764 c.unwrap_net(),
765 );
766 design.add_output("y", y);
767 design.apply();
768 simplify(&mut design);
769 let mut gold = Design::new();
770 let a = gold.add_input("a", 4);
771 let b = gold.add_input("b", 4);
772 let ab = gold.add_input("ab", 1);
773 let c = gold.add_input("c", 1);
774 let y0 = gold.add_adc(a.slice(..2), b.slice(..2), c.unwrap_net());
775 let y2 = gold.add_adc(a.slice(2..), b.slice(2..), ab.unwrap_net());
776 gold.add_output("y", y0.concat(y2));
777 gold.apply();
778 assert_isomorphic!(design, gold);
779 }
780
781 #[test]
782 fn test_adc_split_case1_top() {
783 let mut design = Design::new();
784 let a = design.add_input("a", 4);
785 let b = design.add_input("b", 4);
786 let ab = design.add_input("ab", 1);
787 let c = design.add_input("c", 1);
788 let y = design.add_adc(a.concat(&ab), b.concat(&ab), c.unwrap_net());
789 design.add_output("y", y);
790 design.apply();
791 simplify(&mut design);
792 let mut gold = Design::new();
793 let a = gold.add_input("a", 4);
794 let b = gold.add_input("b", 4);
795 let ab = gold.add_input("ab", 1);
796 let c = gold.add_input("c", 1);
797 let y = gold.add_adc(a, b, c.unwrap_net());
798 gold.add_output("y", y.concat(ab));
799 gold.apply();
800 assert_isomorphic!(design, gold);
801 }
802
803 #[test]
804 fn test_adc_split_case2() {
805 let mut design = Design::new();
806 let a = design.add_input("a", 4);
807 let b = design.add_input("b", 4);
808 let y = design.add_adc(&a, &b, b.lsb());
809 design.add_output("y", y);
810 design.apply();
811 simplify(&mut design);
812 let mut gold = Design::new();
813 let a = gold.add_input("a", 4);
814 let b = gold.add_input("b", 4);
815 let y = gold.add_adc(&a[1..], &b[1..], b.lsb());
816 gold.add_output("y", Value::from(a.lsb()).concat(y));
817 gold.apply();
818 assert_isomorphic!(design, gold);
819 }
820
821 #[test]
822 fn test_adc_split_case2_swap() {
823 let mut design = Design::new();
824 let a = design.add_input("a", 4);
825 let b = design.add_input("b", 4);
826 let y = design.add_adc(&a, &b, a.lsb());
827 design.add_output("y", y);
828 design.apply();
829 simplify(&mut design);
830 let mut gold = Design::new();
831 let a = gold.add_input("a", 4);
832 let b = gold.add_input("b", 4);
833 let y = gold.add_adc(&a[1..], &b[1..], a.lsb());
834 gold.add_output("y", Value::from(b.lsb()).concat(y));
835 gold.apply();
836 assert_isomorphic!(design, gold);
837 }
838
839 #[test]
840 fn test_adc_split_case2_top() {
841 let mut design = Design::new();
842 let a = design.add_input("a", 1);
843 let b = design.add_input("b", 1);
844 let y = design.add_adc(&a, &b, b.lsb());
845 design.add_output("y", y);
846 design.apply();
847 simplify(&mut design);
848 let mut gold = Design::new();
849 let a = gold.add_input("a", 1);
850 let b = gold.add_input("b", 1);
851 gold.add_output("y", a.concat(b));
852 gold.apply();
853 assert_isomorphic!(design, gold);
854 }
855
856 #[test]
857 fn test_adc_split_a_plus_a() {
858 let mut design = Design::new();
859 let a = design.add_input("a", 4);
860 let y = design.add_adc(&a, &a, Net::ZERO);
861 design.add_output("y", y);
862 design.apply();
863 simplify(&mut design);
864 let mut gold = Design::new();
865 let a = gold.add_input("a", 4);
866 gold.add_output("y", Value::from(Net::ZERO).concat(a));
867 gold.apply();
868 assert_isomorphic!(design, gold);
869 }
870
871 #[test]
872 fn test_adc_split_a_plus_a_carry() {
873 let mut design = Design::new();
874 let a = design.add_input("a", 4);
875 let c = design.add_input("c", 1);
876 let y = design.add_adc(&a, &a, c.unwrap_net());
877 design.add_output("y", y);
878 design.apply();
879 simplify(&mut design);
880 let mut gold = Design::new();
881 let a = gold.add_input("a", 4);
882 let c = gold.add_input("c", 1);
883 gold.add_output("y", c.concat(a));
884 gold.apply();
885 assert_isomorphic!(design, gold);
886 }
887
888 #[test]
889 fn test_adc_split_const_lsb() {
890 let mut design = Design::new();
891 let a = design.add_input("a", 4);
892 let b = design.add_input("b", 4);
893 let y = design.add_adc(
894 Value::from(Const::lit("0111")).concat(&a),
895 Value::from(Const::lit("1101")).concat(&b),
896 Net::ZERO,
897 );
898 design.add_output("y", y);
899 design.apply();
900 simplify(&mut design);
901 let mut gold = Design::new();
902 let a = gold.add_input("a", 4);
903 let b = gold.add_input("b", 4);
904 let y = gold.add_adc(a, b, Net::ONE);
905 gold.add_output("y", Value::from(Const::lit("0100")).concat(&y));
906 gold.apply();
907 assert_isomorphic!(design, gold);
908 }
909
910 #[test]
911 fn test_adc_split_const_zero_lsb() {
912 let mut design = Design::new();
913 let a = design.add_input("a", 8);
914 let b = design.add_input("b", 4);
915 let y = design.add_adc(a, Value::zero(4).concat(&b), Net::ZERO);
916 design.add_output("y", y);
917 design.apply();
918 simplify(&mut design);
919 let mut gold = Design::new();
920 let a = gold.add_input("a", 8);
921 let b = gold.add_input("b", 4);
922 let y = gold.add_adc(&a[4..], b, Net::ZERO);
923 gold.add_output("y", a.slice(..4).concat(&y));
924 gold.apply();
925 assert_isomorphic!(design, gold);
926 }
927
928 #[test]
929 fn test_adc_split_const_ones_lsb() {
930 let mut design = Design::new();
931 let a = design.add_input("a", 8);
932 let b = design.add_input("b", 4);
933 let y = design.add_adc(a, Value::from(Const::lit("1111")).concat(&b), Net::ONE);
934 design.add_output("y", y);
935 design.apply();
936 simplify(&mut design);
937 let mut gold = Design::new();
938 let a = gold.add_input("a", 8);
939 let b = gold.add_input("b", 4);
940 let y = gold.add_adc(&a[4..], b, Net::ONE);
941 gold.add_output("y", a.slice(..4).concat(&y));
942 gold.apply();
943 assert_isomorphic!(design, gold);
944 }
945
946 #[test]
947 fn test_adc_split_disjoint() {
948 let mut design = Design::new();
949 let a = design.add_input("a", 4);
950 let b = design.add_input("b", 4);
951 let y = design.add_adc(a.concat(Value::zero(4)), Value::zero(4).concat(&b), Net::ZERO);
952 design.add_output("y", y);
953 design.apply();
954 simplify(&mut design);
955 let mut gold = Design::new();
956 let a = gold.add_input("a", 4);
957 let b = gold.add_input("b", 4);
958 gold.add_output("y", a.concat(&b).concat(Net::ZERO));
959 gold.apply();
960 assert_isomorphic!(design, gold);
961 }
962
963 #[test]
964 fn test_adc_split_zeros() {
965 let mut design = Design::new();
966 let al = design.add_input("al", 4);
967 let ah = design.add_input("ah", 4);
968 let bl = design.add_input("bl", 4);
969 let bh = design.add_input("bh", 4);
970 let y = design.add_adc(al.concat(Value::zero(4)).concat(ah), bl.concat(Value::zero(4)).concat(bh), Net::ZERO);
971 design.add_output("y", y);
972 design.apply();
973 simplify(&mut design);
974 let mut gold = Design::new();
975 let al = gold.add_input("al", 4);
976 let ah = gold.add_input("ah", 4);
977 let bl = gold.add_input("bl", 4);
978 let bh = gold.add_input("bh", 4);
979 let yl = gold.add_adc(al, bl, Net::ZERO);
980 let yh = gold.add_adc(ah, bh, Net::ZERO);
981 gold.add_output("y", yl.concat(Value::zero(3)).concat(yh));
982 gold.apply();
983 assert_isomorphic!(design, gold);
984 }
985
986 #[test]
987 fn test_adc_split_zext() {
988 let mut design = Design::new();
989 let a = design.add_input("a", 4);
990 let b = design.add_input("b", 4);
991 let c = design.add_input("c", 1);
992 let y = design.add_adc(a.concat(Value::zero(4)), b.concat(Value::zero(4)), c.unwrap_net());
993 design.add_output("y", y);
994 design.apply();
995 simplify(&mut design);
996 let mut gold = Design::new();
997 let a = gold.add_input("a", 4);
998 let b = gold.add_input("b", 4);
999 let c = gold.add_input("c", 1);
1000 let y = gold.add_adc(a, b, c.unwrap_net());
1001 gold.add_output("y", y.concat(Value::zero(4)));
1002 gold.apply();
1003 assert_isomorphic!(design, gold);
1004 }
1005
1006 #[test]
1007 fn test_adc_unsext_sext() {
1008 let mut design = Design::new();
1009 let a = design.add_input("a", 4);
1010 let b = design.add_input("b", 4);
1011 let c = design.add_input("c", 1);
1012 let y = design.add_adc(a.sext(8), b.sext(8), c.unwrap_net());
1013 design.add_output("y", y);
1014 design.apply();
1015 simplify(&mut design);
1016 let mut gold = Design::new();
1017 let a = gold.add_input("a", 4);
1018 let b = gold.add_input("b", 4);
1019 let c = gold.add_input("c", 1);
1020 let y = gold.add_adc(a.sext(5), b.sext(5), c.unwrap_net());
1021 gold.add_output("y", y.slice(..5).sext(8).concat(y.msb()));
1022 gold.apply();
1023 assert_isomorphic!(design, gold);
1024 }
1025
1026 #[test]
1027 fn test_adc_unsext_bi() {
1028 let mut design = Design::new();
1029 let al = design.add_input("al", 1);
1030 let bl = design.add_input("bl", 1);
1031 let ah = design.add_input("ah", 1);
1032 let bh = design.add_input("bh", 1);
1033 let c = design.add_input("c", 1);
1034 let y = design.add_adc(al.sext(4).concat(ah.sext(4)), bl.sext(4).concat(bh.sext(4)), c.unwrap_net());
1035 design.add_output("y", y);
1036 design.apply();
1037 simplify(&mut design);
1038 let mut gold = Design::new();
1039 let al = gold.add_input("al", 1);
1040 let bl = gold.add_input("bl", 1);
1041 let ah = gold.add_input("ah", 1);
1042 let bh = gold.add_input("bh", 1);
1043 let c = gold.add_input("c", 1);
1044 let y0 = gold.add_adc(al.sext(2), bl.sext(2), c.unwrap_net());
1045 let y1 = gold.add_adc(ah.sext(2), bh.sext(2), y0.msb());
1046 gold.add_output("y", y0.slice(..2).sext(4).concat(y1.slice(..2).sext(4)).concat(y1.msb()));
1047 gold.apply();
1048 assert_isomorphic!(design, gold);
1049 }
1050
1051 #[test]
1052 fn test_adc_unsext_only2() {
1053 for size in [1, 2] {
1054 let design = Design::new();
1055 let a = design.add_input("a", size);
1056 let b = design.add_input("b", size);
1057 let c = design.add_input("c", 1);
1058 let y = design.add_adc(a.sext(size + 1), b.sext(size + 1), c.unwrap_net());
1059 design.add_output("y", y);
1060 assert_no_simplify!(design);
1061 }
1062 }
1063
1064 #[test]
1065 fn test_adc_unsext_only3() {
1066 for size in [1, 2] {
1067 let mut design = Design::new();
1068 let a = design.add_input("a", size);
1069 let b = design.add_input("b", size);
1070 let c = design.add_input("c", 1);
1071 let y = design.add_adc(a.sext(size + 2), b.sext(size + 2), c.unwrap_net());
1072 design.add_output("y", y);
1073 design.apply();
1074 simplify(&mut design);
1075 simplify(&mut design); let mut gold = Design::new();
1078 let a = gold.add_input("a", size);
1079 let b = gold.add_input("b", size);
1080 let c = gold.add_input("c", 1);
1081 let y = gold.add_adc(a.sext(size + 1), b.sext(size + 1), c.unwrap_net());
1082 gold.add_output("y", y.slice(..size + 1).sext(size + 2).concat(y.msb()));
1083 gold.apply();
1084 assert_isomorphic!(design, gold);
1085 }
1086 }
1087
1088 #[test]
1089 fn test_adc_ci_folding() {
1090 for size in [1, 2] {
1091 assert_simplify!(
1092 |ds| {
1093 ds.add_adc(
1094 ds.add_adc(ds.add_input("a", size), ds.add_input("b", size), Net::ZERO),
1095 ds.add_input("c", 1).zext(size + 1),
1096 Net::ZERO
1097 )
1098 };
1099 [PZExt [PAdc [PInput ("a")] [PInput ("b")] [PInput ("c")]]] => true;
1100 );
1101 }
1102 }
1103
1104 #[test]
1105 fn test_eq_const_eval() {
1106 for (value1, value2) in iter_interesting_const_pairs() {
1107 assert_simplify!(
1108 |ds| ds.add_eq(&value1, &value2);
1109 [PConst@a] => a == Const::from(value1.eq(&value2));
1110 );
1111 }
1112 }
1113
1114 #[test]
1115 fn test_eq_fold() {
1116 assert_simplify!(
1117 |ds| ds.add_eq(Const::ones(1), ds.add_input("a", 1)),
1118 |ds| ds.add_eq(ds.add_input("a", 1), Const::ones(1));
1119 [PInput ("a")] => true;
1120 );
1121 assert_simplify!(
1122 |ds| ds.add_eq(Const::zero(1), ds.add_input("a", 1)),
1123 |ds| ds.add_eq(ds.add_input("a", 1), Const::zero(1));
1124 [PNot [PInput ("a")]] => true;
1125 );
1126 for size in [1, 2] {
1127 assert_simplify!(
1128 |ds| {let a = ds.add_input("a", size); ds.add_eq(&a, &a)};
1129 [POnes] => true;
1130 );
1131 }
1132 }
1133
1134 #[test]
1135 fn test_ult_const_eval() {
1136 for (value1, value2) in iter_interesting_const_pairs() {
1137 assert_simplify!(
1138 |ds| ds.add_ult(&value1, &value2);
1139 [PConst@a] => a == Const::from(value1.ult(&value2));
1140 );
1141 }
1142 }
1143
1144 #[test]
1145 fn test_ult_fold() {
1146 for size in [1, 2] {
1147 assert_simplify!(
1148 |ds| ds.add_ult(ds.add_input("a", size), Value::zero(size));
1149 [PZero] => true;
1150 );
1151 assert_simplify!(
1152 |ds| ds.add_ult(Value::ones(size), ds.add_input("a", size));
1153 [PZero] => true;
1154 );
1155 for a in iter_has_undef_consts().filter(|c| c.len() == size) {
1156 assert_simplify!(
1157 |ds| ds.add_ult(&a, ds.add_input("a", size)),
1158 |ds| ds.add_ult(ds.add_input("a", size), &a);
1159 [PUndef] => true;
1160 );
1161 }
1162 assert_simplify!(
1163 |ds| {let a = ds.add_input("a", size); ds.add_ult(&a, &a)};
1164 [PZero] => true;
1165 );
1166 }
1167 }
1168
1169 #[test]
1170 fn test_slt_const_eval() {
1171 for (value1, value2) in iter_interesting_const_pairs() {
1172 assert_simplify!(
1173 |ds| ds.add_slt(&value1, &value2);
1174 [PConst@a] => a == Const::from(value1.slt(&value2));
1175 );
1176 }
1177 }
1178
1179 #[test]
1180 fn test_slt_fold() {
1181 for size in [1, 2] {
1182 for a in iter_has_undef_consts().filter(|c| c.len() == size) {
1183 assert_simplify!(
1184 |ds| ds.add_slt(&a, ds.add_input("a", size)),
1185 |ds| ds.add_slt(ds.add_input("a", size), &a);
1186 [PUndef] => true;
1187 );
1188 }
1189 assert_simplify!(
1190 |ds| {let a = ds.add_input("a", size); ds.add_slt(&a, &a)};
1191 [PZero] => true;
1192 );
1193 }
1194 }
1195
1196 #[test]
1197 fn test_shl_fold() {
1198 for size in [2, 4] {
1199 for size2 in [2, 4] {
1200 assert_simplify!(
1201 |ds| ds.add_shl(Value::zero(size), ds.add_input("a", size2), 1);
1202 [PZero] => true;
1203 );
1204 assert_simplify!(
1205 |ds| ds.add_shl(ds.add_input("a", size), ds.add_input("b", size2), 0);
1206 [PInput ("a")] => true;
1207 );
1208 }
1209 }
1210 }
1211
1212 #[test]
1213 fn test_ff_simplify_clear() {
1214 for size in [1, 2] {
1215 let design = Design::new();
1216 let flip_flop = FlipFlop::new(design.add_input("d", size), design.add_input1("c"))
1217 .with_clear(ControlNet::Pos(design.add_not(design.add_input("r", 1))[0]));
1218 design.add_output("q", design.add_dff(flip_flop));
1219 let gold = Design::new();
1220 let flip_flop = FlipFlop::new(gold.add_input("d", size), gold.add_input1("c"))
1221 .with_clear(ControlNet::Neg(gold.add_input1("r")));
1222 gold.add_output("q", gold.add_dff(flip_flop));
1223 assert_simplify_isomorphic!(design, gold);
1224 }
1225 for size in [1, 2] {
1226 let design = Design::new();
1227 let flip_flop = FlipFlop::new(design.add_input("d", size), design.add_input1("c"))
1228 .with_clear(ControlNet::Neg(design.add_not(design.add_input("r", 1))[0]));
1229 design.add_output("q", design.add_dff(flip_flop));
1230 let gold = Design::new();
1231 let flip_flop = FlipFlop::new(gold.add_input("d", size), gold.add_input1("c"))
1232 .with_clear(ControlNet::Pos(gold.add_input1("r")));
1233 gold.add_output("q", gold.add_dff(flip_flop));
1234 assert_simplify_isomorphic!(design, gold);
1235 }
1236 }
1237
1238 #[test]
1239 fn test_ff_simplify_reset() {
1240 for size in [1, 2] {
1241 let design = Design::new();
1242 let flip_flop = FlipFlop::new(design.add_input("d", size), design.add_input1("c"))
1243 .with_reset(ControlNet::Pos(design.add_not(design.add_input("r", 1))[0]));
1244 design.add_output("q", design.add_dff(flip_flop));
1245 let gold = Design::new();
1246 let flip_flop = FlipFlop::new(gold.add_input("d", size), gold.add_input1("c"))
1247 .with_reset(ControlNet::Neg(gold.add_input1("r")));
1248 gold.add_output("q", gold.add_dff(flip_flop));
1249 assert_simplify_isomorphic!(design, gold);
1250 }
1251 for size in [1, 2] {
1252 let design = Design::new();
1253 let flip_flop = FlipFlop::new(design.add_input("d", size), design.add_input1("c"))
1254 .with_reset(ControlNet::Neg(design.add_not(design.add_input("r", 1))[0]));
1255 design.add_output("q", design.add_dff(flip_flop));
1256 let gold = Design::new();
1257 let flip_flop = FlipFlop::new(gold.add_input("d", size), gold.add_input1("c"))
1258 .with_reset(ControlNet::Pos(gold.add_input1("r")));
1259 gold.add_output("q", gold.add_dff(flip_flop));
1260 assert_simplify_isomorphic!(design, gold);
1261 }
1262 }
1263
1264 #[test]
1265 fn test_ff_simplify_enable() {
1266 for size in [1, 2] {
1267 let design = Design::new();
1268 let flip_flop = FlipFlop::new(design.add_input("d", size), design.add_input1("c"))
1269 .with_enable(ControlNet::Pos(design.add_not(design.add_input("e", 1))[0]));
1270 design.add_output("q", design.add_dff(flip_flop));
1271 let gold = Design::new();
1272 let flip_flop = FlipFlop::new(gold.add_input("d", size), gold.add_input1("c"))
1273 .with_enable(ControlNet::Neg(gold.add_input1("e")));
1274 gold.add_output("q", gold.add_dff(flip_flop));
1275 assert_simplify_isomorphic!(design, gold);
1276 }
1277 for size in [1, 2] {
1278 let design = Design::new();
1279 let flip_flop = FlipFlop::new(design.add_input("d", size), design.add_input1("c"))
1280 .with_enable(ControlNet::Neg(design.add_not(design.add_input("e", 1))[0]));
1281 design.add_output("q", design.add_dff(flip_flop));
1282 let gold = Design::new();
1283 let flip_flop = FlipFlop::new(gold.add_input("d", size), gold.add_input1("c"))
1284 .with_enable(ControlNet::Pos(gold.add_input1("e")));
1285 gold.add_output("q", gold.add_dff(flip_flop));
1286 assert_simplify_isomorphic!(design, gold);
1287 }
1288 }
1289
1290 #[test]
1291 fn test_ff_canonicalize_controls() {
1292 let design = Design::new();
1293 let flip_flop = FlipFlop::new(design.add_input("d", 1), ControlNet::Neg(Net::ONE))
1294 .with_clear(ControlNet::Neg(Net::ONE))
1295 .with_reset(ControlNet::Neg(Net::ONE))
1296 .with_enable(ControlNet::Neg(Net::ONE));
1297 design.add_output("q", design.add_dff(flip_flop));
1298 let gold = Design::new();
1299 let flip_flop = FlipFlop::new(Value::undef(1), Net::ZERO).with_enable(ControlNet::Pos(Net::ZERO));
1300 gold.add_output("q", gold.add_dff(flip_flop));
1301 assert_simplify_isomorphic!(design, gold);
1302 }
1303
1304 #[test]
1305 fn test_ff_simplify_clock_const() {
1306 let design = Design::new();
1307 let flip_flop = FlipFlop::new(design.add_input("d", 1), Net::ZERO)
1308 .with_reset(design.add_input1("r"))
1309 .with_enable(design.add_input1("e"));
1310 design.add_output("q", design.add_dff(flip_flop));
1311 let gold = Design::new();
1312 let flip_flop = FlipFlop::new(Value::undef(1), Net::ZERO).with_enable(ControlNet::Pos(Net::ZERO));
1313 gold.add_output("q", gold.add_dff(flip_flop));
1314 assert_simplify_isomorphic!(design, gold);
1315 }
1316
1317 #[test]
1318 fn test_ff_simplify_reset_always_enable_prio() {
1319 for init in &[Const::undef(1), Const::zero(1), Const::ones(1)] {
1320 let design = Design::new();
1321 let flip_flop = FlipFlop::new(design.add_input("d", 1), design.add_input1("c"))
1322 .with_enable(design.add_input1("e"))
1323 .with_reset(Net::ONE)
1324 .with_init(init.clone());
1325 design.add_output("q", design.add_dff(flip_flop));
1326 let gold = Design::new();
1327 let flip_flop = FlipFlop::new(init.into(), gold.add_input1("c"))
1328 .with_enable(gold.add_input1("e"))
1329 .with_init(init.clone());
1330 gold.add_output("q", gold.add_dff(flip_flop));
1331 assert_simplify_isomorphic!(design, gold);
1332 }
1333 }
1334
1335 #[test]
1336 fn test_ff_simplify_reset_always_reset_prio() {
1337 for init in &[Const::undef(1), Const::zero(1), Const::ones(1)] {
1338 let design = Design::new();
1339 let flip_flop = FlipFlop::new(design.add_input("d", 1), design.add_input1("c"))
1340 .with_reset(Net::ONE)
1341 .with_enable(design.add_input1("e"))
1342 .with_init(init.clone());
1343 design.add_output("q", design.add_dff(flip_flop));
1344 let gold = Design::new();
1345 let flip_flop =
1346 FlipFlop::new(init.into(), gold.add_input1("c")).with_enable(Net::ONE).with_init(init.clone());
1347 gold.add_output("q", gold.add_dff(flip_flop));
1348 assert_simplify_isomorphic!(design, gold);
1349 }
1350 }
1351
1352 #[test]
1353 fn test_ff_simplify_enable_never_enable_prio() {
1354 for init in &[Const::undef(1), Const::zero(1), Const::ones(1)] {
1355 let design = Design::new();
1356 let flip_flop = FlipFlop::new(design.add_input("d", 1), design.add_input1("c"))
1357 .with_enable(Net::ZERO)
1358 .with_reset(design.add_input1("r"))
1359 .with_init(init.clone());
1360 design.add_output("q", design.add_dff(flip_flop));
1361 let gold = Design::new();
1362 let flip_flop = FlipFlop::new(Value::undef(1), Net::ZERO)
1363 .with_reset(Net::ZERO)
1364 .with_enable(Net::ZERO)
1365 .with_init(init.clone());
1366 gold.add_output("q", gold.add_dff(flip_flop));
1367 assert_simplify_isomorphic!(design, gold);
1368 }
1369 }
1370
1371 #[test]
1372 fn test_ff_simplify_enable_never_reset_prio() {
1373 for init in &[Const::undef(1), Const::zero(1), Const::ones(1)] {
1374 let design = Design::new();
1375 let flip_flop = FlipFlop::new(design.add_input("d", 1), design.add_input1("c"))
1376 .with_reset(design.add_input1("r"))
1377 .with_enable(Net::ZERO)
1378 .with_init(init.clone());
1379 design.add_output("q", design.add_dff(flip_flop));
1380 let gold = Design::new();
1381 let flip_flop = FlipFlop::new(init.into(), gold.add_input1("c"))
1382 .with_reset(Net::ZERO)
1383 .with_enable(gold.add_input1("r"))
1384 .with_init(init.clone());
1385 gold.add_output("q", gold.add_dff(flip_flop));
1386 assert_simplify_isomorphic!(design, gold);
1387 }
1388 }
1389
1390 #[test]
1391 fn test_ff_simplify_always_clear() {
1392 for init in &[Const::undef(1), Const::zero(1), Const::ones(1)] {
1393 let mut design = Design::new();
1394 let flip_flop = FlipFlop::new(design.add_input("d", 1), design.add_input1("c"))
1395 .with_clear(Net::ONE)
1396 .with_init(init.clone());
1397 design.add_output("q", design.add_dff(flip_flop));
1398 design.apply();
1399 simplify(&mut design);
1400 assert_netlist!(design, netlist_match! { [PConst@c] => c == *init; });
1401 }
1402 }
1403
1404 #[test]
1405 fn test_ff_reset_pos_matching() {
1406 for init in &[Const::undef(1), Const::zero(1), Const::ones(1)] {
1407 let design = Design::new();
1408 let d = design.add_mux(design.add_input1("r"), init, design.add_input("d", 1));
1409 design.add_output("q", design.add_dff(FlipFlop::new(d, design.add_input1("c"))));
1410 let gold = Design::new();
1411 let ff = FlipFlop::new(gold.add_input("d", 1), gold.add_input1("c"))
1412 .with_reset_value(ControlNet::Pos(gold.add_input1("r")), init.clone());
1413 gold.add_output("q", gold.add_dff(ff));
1414 assert_simplify_isomorphic!(design, gold);
1415 }
1416 }
1417
1418 #[test]
1419 fn test_ff_reset_neg_matching() {
1420 for init in &[Const::undef(1), Const::zero(1), Const::ones(1)] {
1421 let design = Design::new();
1422 let d = design.add_mux(design.add_input1("r"), design.add_input("d", 1), init);
1423 design.add_output("q", design.add_dff(FlipFlop::new(d, design.add_input1("c"))));
1424 let gold = Design::new();
1425 let ff = FlipFlop::new(gold.add_input("d", 1), gold.add_input1("c"))
1426 .with_reset_value(ControlNet::Neg(gold.add_input1("r")), init.clone());
1427 gold.add_output("q", gold.add_dff(ff));
1428 assert_simplify_isomorphic!(design, gold);
1429 }
1430 }
1431
1432 #[test]
1433 fn test_ff_enable_pos_matching() {
1434 let design = Design::new();
1435 let q = design.add_void(1);
1436 let d = design.add_mux(design.add_input1("e"), design.add_input("d", 1), q.clone());
1437 design.replace_value(&q, design.add_dff(FlipFlop::new(d, design.add_input1("c"))));
1438 design.add_output("q", q);
1439 let gold = Design::new();
1440 let ff = FlipFlop::new(gold.add_input("d", 1), gold.add_input1("c"))
1441 .with_enable(ControlNet::Pos(gold.add_input1("e")));
1442 gold.add_output("q", gold.add_dff(ff));
1443 assert_simplify_isomorphic!(design, gold);
1444 }
1445
1446 #[test]
1447 fn test_ff_enable_neg_matching() {
1448 let design = Design::new();
1449 let q = design.add_void(1);
1450 let d = design.add_mux(design.add_input1("e"), q.clone(), design.add_input("d", 1));
1451 design.replace_value(&q, design.add_dff(FlipFlop::new(d, design.add_input1("c"))));
1452 design.add_output("q", q);
1453 let gold = Design::new();
1454 let ff = FlipFlop::new(gold.add_input("d", 1), gold.add_input1("c"))
1455 .with_enable(ControlNet::Neg(gold.add_input1("e")));
1456 gold.add_output("q", gold.add_dff(ff));
1457 assert_simplify_isomorphic!(design, gold);
1458 }
1459
1460 #[test]
1461 fn test_iobuf_simplify_enable() {
1462 for size in [1, 2] {
1463 let design = Design::new();
1464 let io_buffer = IoBuffer {
1465 io: design.add_io("io", size),
1466 output: design.add_input("o", size),
1467 enable: ControlNet::Pos(design.add_not(design.add_input("e", 1))[0]),
1468 };
1469 design.add_output("i", design.add_iobuf(io_buffer));
1470 let gold = Design::new();
1471 let io_buffer = IoBuffer {
1472 io: gold.add_io("io", size),
1473 output: gold.add_input("o", size),
1474 enable: ControlNet::Neg(gold.add_input1("e")),
1475 };
1476 gold.add_output("i", gold.add_iobuf(io_buffer));
1477 assert_simplify_isomorphic!(design, gold);
1478 }
1479 for size in [1, 2] {
1480 let design = Design::new();
1481 let io_buffer = IoBuffer {
1482 io: design.add_io("io", size),
1483 output: design.add_input("o", size),
1484 enable: ControlNet::Neg(design.add_not(design.add_input("e", 1))[0]),
1485 };
1486 design.add_output("i", design.add_iobuf(io_buffer));
1487 let gold = Design::new();
1488 let io_buffer = IoBuffer {
1489 io: gold.add_io("io", size),
1490 output: gold.add_input("o", size),
1491 enable: ControlNet::Pos(gold.add_input1("e")),
1492 };
1493 gold.add_output("i", gold.add_iobuf(io_buffer));
1494 assert_simplify_isomorphic!(design, gold);
1495 }
1496 }
1497
1498 #[test]
1499 fn test_iobuf_canonicalize_controls() {
1500 let design = Design::new();
1501 let io_buffer = IoBuffer {
1502 io: design.add_io("io", 1),
1503 output: design.add_input("o", 1),
1504 enable: ControlNet::Neg(Net::ONE),
1505 };
1506 design.add_output("i", design.add_iobuf(io_buffer));
1507 let gold = Design::new();
1508 let io_buffer =
1509 IoBuffer { io: gold.add_io("io", 1), output: gold.add_input("o", 1), enable: ControlNet::Pos(Net::ZERO) };
1510 gold.add_output("i", gold.add_iobuf(io_buffer));
1511 assert_simplify_isomorphic!(design, gold);
1512 }
1513
1514 #[cfg(not(feature = "verify"))]
1515 #[test]
1516 fn test_target_cell_simplify() {
1517 let target = MockTarget::new();
1518 let prototype = target.prototype("BUF1").unwrap();
1519 let design = Design::with_target(Some(target.clone()));
1520 let mut target_cell = TargetCell::new("BUF1", prototype);
1521 prototype.apply_input(&mut target_cell, "I", design.add_not(design.add_input("i", 1)));
1522 design.add_output("o", design.add_target(target_cell));
1523 let gold = Design::with_target(Some(target.clone()));
1524 let mut target_cell = TargetCell::new("BUF1", prototype);
1525 prototype.apply_input(&mut target_cell, "I", gold.add_input("i", 1));
1526 prototype.apply_param(&mut target_cell, "INVERT", Const::ones(1));
1527 gold.add_output("o", gold.add_target(target_cell));
1528 assert_simplify_isomorphic!(design, gold);
1529 }
1530}