prjunnamed_generic/rewrite/
lower.rs1use 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
99pub 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}