prjunnamed_pattern/
arithmetic.rs

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}