prjunnamed_generic/rewrite/
lower.rs

1use prjunnamed_netlist::{Cell, MetaItemRef, Net, RewriteResult, RewriteRuleset, Rewriter, Value};
2
3pub struct LowerMux;
4
5impl RewriteRuleset for LowerMux {
6    fn rewrite<'a>(
7        &self,
8        cell: &Cell,
9        _meta: MetaItemRef<'a>,
10        _output: Option<&Value>,
11        rewriter: &Rewriter<'a>,
12    ) -> RewriteResult<'a> {
13        let &Cell::Mux(sel, ref val1, ref val2) = cell else {
14            return RewriteResult::None;
15        };
16        let sel = sel.repeat(val1.len());
17        let nsel = rewriter.add_cell(Cell::Not(sel.clone()));
18        let term1 = rewriter.add_cell(Cell::And(sel, val1.clone()));
19        let term2 = rewriter.add_cell(Cell::And(nsel, val2.clone()));
20        return Cell::Or(term1, term2).into();
21    }
22}
23
24pub struct LowerEq;
25
26impl RewriteRuleset for LowerEq {
27    fn rewrite<'a>(
28        &self,
29        cell: &Cell,
30        _meta: MetaItemRef<'a>,
31        _output: Option<&Value>,
32        rewriter: &Rewriter<'a>,
33    ) -> RewriteResult<'a> {
34        let &Cell::Eq(ref val1, ref val2) = cell else {
35            return RewriteResult::None;
36        };
37        let xor = rewriter.add_cell(Cell::Xor(val1.clone(), val2.clone()));
38        let xnor = rewriter.add_cell(Cell::Not(xor));
39        let mut eq = Net::ONE;
40        for bit in xnor {
41            eq = rewriter.add_cell(Cell::And(eq.into(), bit.into()))[0];
42        }
43        eq.into()
44    }
45}
46
47pub struct LowerLt;
48
49impl RewriteRuleset for LowerLt {
50    fn rewrite<'a>(
51        &self,
52        cell: &Cell,
53        _meta: MetaItemRef<'a>,
54        _output: Option<&Value>,
55        rewriter: &Rewriter<'a>,
56    ) -> RewriteResult<'a> {
57        match cell {
58            Cell::ULt(a, b) => {
59                let b_inv = rewriter.add_cell(Cell::Not(b.clone()));
60                let sub = rewriter.add_cell(Cell::Adc(a.clone(), b_inv, Net::ONE));
61                Cell::Not(sub.msb().into()).into()
62            }
63            Cell::SLt(a, b) => {
64                let a_inv = a.slice(..a.len() - 1).concat(rewriter.add_cell(Cell::Not(a.msb().into())));
65                let b_inv = rewriter.add_cell(Cell::Not(b.slice(..b.len() - 1))).concat(b.msb());
66                let sub = rewriter.add_cell(Cell::Adc(a_inv, b_inv, Net::ONE));
67                Cell::Not(sub.msb().into()).into()
68            }
69            _ => RewriteResult::None,
70        }
71    }
72}
73
74pub struct LowerMul;
75
76impl RewriteRuleset for LowerMul {
77    fn rewrite<'a>(
78        &self,
79        cell: &Cell,
80        _meta: MetaItemRef<'a>,
81        _output: Option<&Value>,
82        rewriter: &Rewriter<'a>,
83    ) -> RewriteResult<'a> {
84        let &Cell::Mul(ref a, ref b) = cell else {
85            return RewriteResult::None;
86        };
87        let mut value = Value::zero(a.len());
88        for (index, bit) in b.iter().enumerate() {
89            value = rewriter.add_cell(Cell::Adc(
90                value,
91                Value::zero(index).concat(rewriter.add_cell(Cell::Mux(bit, a.clone(), Value::zero(a.len())))),
92                Net::ZERO,
93            ));
94        }
95        value.slice(..a.len()).into()
96    }
97}
98
99// TODO: Div (all kinds)
100
101pub struct LowerShift;
102
103impl RewriteRuleset for LowerShift {
104    fn rewrite<'a>(
105        &self,
106        cell: &Cell,
107        _meta: MetaItemRef<'a>,
108        _output: Option<&Value>,
109        rewriter: &Rewriter<'a>,
110    ) -> RewriteResult<'a> {
111        enum Mode {
112            Shl,
113            UShr,
114            SShr,
115            XShr,
116        }
117        let (value, amount, stride, mode, overflow) = match cell {
118            &Cell::Shl(ref a, ref b, stride) => (a, b, stride, Mode::Shl, Value::zero(a.len())),
119            &Cell::UShr(ref a, ref b, stride) => (a, b, stride, Mode::UShr, Value::zero(a.len())),
120            &Cell::SShr(ref a, ref b, stride) => (a, b, stride, Mode::SShr, a.msb().repeat(a.len())),
121            &Cell::XShr(ref a, ref b, stride) => (a, b, stride, Mode::XShr, Value::undef(a.len())),
122            _ => return RewriteResult::None,
123        };
124        let mut stride = stride as usize;
125        let mut value = value.clone();
126        for (index, bit) in amount.iter().enumerate() {
127            if stride < value.len() {
128                let shifted = match mode {
129                    Mode::Shl => Value::zero(stride).concat(value.slice(..value.len() - stride)),
130                    Mode::UShr => value.slice(stride..).zext(value.len()),
131                    Mode::SShr => value.slice(stride..).sext(value.len()),
132                    Mode::XShr => value.slice(stride..).concat(Value::undef(stride)),
133                };
134                value = rewriter.add_cell(Cell::Mux(bit, shifted, value));
135                stride *= 2;
136            } else {
137                let rest = amount.slice(index + 1..);
138                let rest_len = rest.len();
139                let no_overflow = rewriter.add_cell(Cell::Eq(rest, Value::zero(rest_len)));
140                value = rewriter.add_cell(Cell::Mux(no_overflow[0], value, overflow));
141                break;
142            }
143        }
144        value.into()
145    }
146}