1use prjunnamed_netlist::{Cell, Net, Value};
2
3use crate::{DesignDyn, NetOrValue, Pattern};
4
5pub struct PAdc<P1, P2, P3>(P1, P2, P3);
6
7impl<P1, P2, P3> PAdc<P1, P2, P3> {
8 pub fn new(pat1: P1, pat2: P2, pat3: P3) -> PAdc<P1, P2, P3> {
9 PAdc(pat1, pat2, pat3)
10 }
11}
12
13impl<P1: Pattern<Value>, P2: Pattern<Value>, P3: Pattern<Net>> Pattern<Value> for PAdc<P1, P2, P3> {
14 type Capture = (Value, P1::Capture, P2::Capture, P3::Capture);
15
16 #[inline]
17 fn execute(&self, design: &dyn DesignDyn, target: &Value) -> Option<Self::Capture> {
18 if target.is_empty() {
19 return None;
20 }
21 let (cap1, cap2, cap3);
22 if let Ok((cell_ref, _offset)) = design.find_cell(target.iter().next().unwrap()) {
23 if let Cell::Adc(arg1, arg2, arg3) = &*cell_ref.get() {
24 if *target == cell_ref.output() {
25 cap1 = arg1.clone();
26 cap2 = arg2.clone();
27 cap3 = *arg3;
28 } else {
29 return None;
30 }
31 } else {
32 return None;
33 }
34 } else {
35 return None;
36 }
37 self.0.execute(design, &cap1).and_then(|cap1| {
38 self.1.execute(design, &cap2).and_then(|cap2| {
39 self.2.execute(design, &cap3).and_then(|cap3| Some((target.clone(), cap1, cap2, cap3)))
40 })
41 })
42 }
43}
44
45macro_rules! compare_patterns {
46 {} => {};
47
48 { $name:ident(_,_) => $cstr:ident; $($rest:tt)* } => {
49 pub struct $name<P1, P2>(P1, P2);
50
51 impl<P1, P2> $name<P1, P2> {
52 pub fn new(pat1: P1, pat2: P2) -> $name<P1, P2> {
53 $name(pat1, pat2)
54 }
55 }
56
57 impl<T: NetOrValue, P1: Pattern<Value>, P2: Pattern<Value>> Pattern<T> for $name<P1, P2> {
58 type Capture = (Net, P1::Capture, P2::Capture);
59
60 #[inline]
61 fn execute(&self, design: &dyn DesignDyn, target: &T) -> Option<Self::Capture> {
62 if target.len() != 1 { return None }
63 let target = target.iter().next().unwrap();
64 let (cap1, cap2);
65 if let Ok((cell_ref, 0)) = design.find_cell(target) {
66 if let Cell::$cstr(arg1, arg2) = &*cell_ref.get() {
67 cap1 = arg1.clone();
68 cap2 = arg2.clone();
69 } else {
70 return None
71 }
72 } else {
73 return None
74 }
75 self.0.execute(design, &cap1).and_then(|cap1|
76 self.1.execute(design, &cap2).and_then(|cap2|
77 Some((target, cap1, cap2))))
78 }
79 }
80
81 compare_patterns!{ $($rest)* }
82 }
83}
84
85macro_rules! arithmetic_patterns {
86 {} => {};
87
88 { $name:ident(_,_) => $cstr:ident; $($rest:tt)* } => {
89 pub struct $name<P1, P2>(P1, P2);
90
91 impl<P1, P2> $name<P1, P2> {
92 pub fn new(pat1: P1, pat2: P2) -> $name<P1, P2> {
93 $name(pat1, pat2)
94 }
95 }
96
97 impl<P1: Pattern<Value>, P2: Pattern<Value>> Pattern<Value> for $name<P1, P2> {
98 type Capture = (Value, P1::Capture, P2::Capture);
99
100 #[inline]
101 fn execute(&self, design: &dyn DesignDyn, target: &Value) -> Option<Self::Capture> {
102 if target.is_empty() { return None }
103 let (cap1, cap2);
104 if let Ok((cell_ref, 0)) = design.find_cell(target.iter().next().unwrap()) {
105 if let Cell::$cstr(arg1, arg2) = &*cell_ref.get() {
106 if *target == cell_ref.output() {
107 cap1 = arg1.clone();
108 cap2 = arg2.clone();
109 } else {
110 return None
111 }
112 } else {
113 return None
114 }
115 } else {
116 return None
117 }
118 self.0.execute(design, &cap1).and_then(|cap1|
119 self.1.execute(design, &cap2).and_then(|cap2|
120 Some((target.clone(), cap1, cap2))))
121 }
122 }
123
124 arithmetic_patterns!{ $($rest)* }
125 }
126}
127
128compare_patterns! {
129 PEq(_,_) => Eq;
130 PULt(_,_) => ULt;
131 PSLt(_,_) => SLt;
132}
133
134arithmetic_patterns! {
135 PMul(_,_) => Mul;
136 PUDiv(_,_) => UDiv;
137 PUMod(_,_) => UMod;
138 PSDivTrunc(_,_) => SDivTrunc;
139 PSDivFloor(_,_) => SDivFloor;
140 PSModTrunc(_,_) => SModTrunc;
141 PSModFloor(_,_) => SModFloor;
142}