1use linked_hash_map::LinkedHashMap;
2
3use crate::control::StaticInvoke;
4use crate::{self as ir, RRC};
5use std::borrow::BorrowMut;
6use std::cell::RefCell;
7use std::collections::HashMap;
8use std::rc::Rc;
9
10pub type RewriteMap<T> = HashMap<ir::Id, RRC<T>>;
12
13pub type PortRewriteMap = LinkedHashMap<ir::Canonical, RRC<ir::Port>>;
16
17#[derive(Default)]
18pub struct Rewriter {
22 pub port_map: PortRewriteMap,
24 pub cell_map: RewriteMap<ir::Cell>,
26 pub group_map: RewriteMap<ir::Group>,
28 pub comb_group_map: RewriteMap<ir::CombGroup>,
30 pub static_group_map: RewriteMap<ir::StaticGroup>,
32}
33
34impl Rewriter {
35 pub fn get_cell_rewrite(&self, cell: &ir::Id) -> Option<RRC<ir::Cell>> {
37 self.cell_map.get(cell).map(Rc::clone)
38 }
39
40 #[inline]
52 fn get_cell_port_rewrite(
53 &self,
54 port_ref: &RRC<ir::Port>,
55 ) -> Option<RRC<ir::Port>> {
56 if self.cell_map.is_empty() {
57 return None;
58 }
59
60 let port = port_ref.borrow();
61 let new_cell = if let ir::PortParent::Cell(cell_wref) = &port.parent {
62 let cell_ref = cell_wref.upgrade();
63 let cell = cell_ref.borrow();
64 self.cell_map.get(&cell.name())
65 } else {
66 None
67 };
68 new_cell.map(|new_cell| Rc::clone(&new_cell.borrow().get(&port.name)))
70 }
71
72 #[inline]
74 fn get_port_rewrite(
75 &self,
76 port_ref: &RRC<ir::Port>,
77 ) -> Option<RRC<ir::Port>> {
78 if self.port_map.is_empty() {
79 return None;
80 }
81
82 let port = port_ref.borrow();
83 self.port_map.get(&port.canonical()).map(Rc::clone)
84 }
85
86 #[inline]
88 pub fn get(&self, port_ref: &RRC<ir::Port>) -> Option<RRC<ir::Port>> {
89 self.get_port_rewrite(port_ref)
90 .or_else(|| self.get_cell_port_rewrite(port_ref))
91 }
92
93 pub fn rewrite_guard<T>(&self, guard: &mut ir::Guard<T>) {
95 match guard {
96 ir::Guard::And(l, r) | ir::Guard::Or(l, r) => {
97 self.rewrite_guard(l.borrow_mut());
98 self.rewrite_guard(r.borrow_mut())
99 }
100 ir::Guard::Not(g) => self.rewrite_guard(g.borrow_mut()),
101 ir::Guard::CompOp(_, l, r) => {
102 if let Some(nl) = self.get(l) {
103 *l = nl;
104 }
105 if let Some(nr) = self.get(r) {
106 *r = nr;
107 }
108 }
109 ir::Guard::Port(p) => {
110 if let Some(np) = self.get(p) {
111 *p = np;
112 }
113 }
114 ir::Guard::Info(_) | ir::Guard::True => (),
115 }
116 }
117
118 pub fn rewrite_assign<T>(&self, assign: &mut ir::Assignment<T>) {
120 if let Some(dst) = self.get(&assign.dst) {
121 assign.dst = dst;
122 }
123 if let Some(src) = self.get(&assign.src) {
124 assign.src = src;
125 }
126 self.rewrite_guard(&mut assign.guard);
127 }
128
129 pub fn rewrite_invoke(&self, inv: &mut ir::Invoke) {
132 let name = inv.comp.borrow().name();
134 if let Some(new_cell) = &self.get_cell_rewrite(&name) {
135 inv.comp = Rc::clone(new_cell);
136 }
137
138 if let Some(cg_ref) = &inv.comb_group {
140 let cg = cg_ref.borrow().name();
141 if let Some(new_cg) = &self.comb_group_map.get(&cg) {
142 inv.comb_group = Some(Rc::clone(new_cg));
143 }
144 }
145
146 inv.inputs
148 .iter_mut()
149 .chain(inv.outputs.iter_mut())
150 .for_each(|(_, port)| {
151 if let Some(new_port) = self.get(&*port) {
152 *port = new_port;
153 }
154 });
155 }
156
157 pub fn rewrite_static_invoke(&self, inv: &mut StaticInvoke) {
159 let name = inv.comp.borrow().name();
161 if let Some(new_cell) = &self.get_cell_rewrite(&name) {
162 inv.comp = Rc::clone(new_cell);
163 }
164
165 inv.inputs
167 .iter_mut()
168 .chain(inv.outputs.iter_mut())
169 .for_each(|(_, port)| {
170 if let Some(new_port) = self.get(&*port) {
171 *port = new_port;
172 }
173 });
174 }
175
176 pub fn rewrite_static_control(&self, sc: &mut ir::StaticControl) {
179 match sc {
180 ir::StaticControl::Empty(_) => (),
181 ir::StaticControl::Enable(sen) => {
182 let g = &sen.group.borrow().name();
183 if let Some(new_group) = self.static_group_map.get(g) {
184 sen.group = Rc::clone(new_group);
185 }
186 }
187 ir::StaticControl::Repeat(rep) => {
188 self.rewrite_static_control(&mut rep.body)
189 }
190 ir::StaticControl::Seq(ir::StaticSeq { stmts, .. })
191 | ir::StaticControl::Par(ir::StaticPar { stmts, .. }) => stmts
192 .iter_mut()
193 .for_each(|c| self.rewrite_static_control(c)),
194 ir::StaticControl::If(sif) => {
195 if let Some(new_port) = self.get(&sif.port) {
197 sif.port = new_port;
198 }
199 self.rewrite_static_control(&mut sif.tbranch);
201 self.rewrite_static_control(&mut sif.fbranch);
202 }
203 ir::StaticControl::Invoke(sin) => {
204 self.rewrite_static_invoke(sin);
205 }
206 }
207 }
208
209 pub fn rewrite_control(&self, c: &mut ir::Control) {
212 match c {
213 ir::Control::Empty(_) => (),
214
215 ir::Control::Enable(en) => {
216 let g = &en.group.borrow().name();
217 if let Some(new_group) = self.group_map.get(g) {
218 en.group = Rc::clone(new_group);
219 }
220 }
221 ir::Control::Seq(ir::Seq { stmts, .. })
222 | ir::Control::Par(ir::Par { stmts, .. }) => {
223 stmts.iter_mut().for_each(|c| self.rewrite_control(c))
224 }
225 ir::Control::If(ife) => {
226 if let Some(new_port) = self.get(&ife.port) {
228 ife.port = new_port;
229 }
230 if let Some(cg_ref) = &ife.cond {
232 let cg = cg_ref.borrow().name();
233 if let Some(new_cg) = &self.comb_group_map.get(&cg) {
234 ife.cond = Some(Rc::clone(new_cg));
235 }
236 }
237 self.rewrite_control(&mut ife.tbranch);
239 self.rewrite_control(&mut ife.fbranch);
240 }
241 ir::Control::While(wh) => {
242 if let Some(new_port) = self.get(&wh.port) {
244 wh.port = new_port;
245 }
246 if let Some(cg_ref) = &wh.cond {
248 let cg = cg_ref.borrow().name();
249 if let Some(new_cg) = &self.comb_group_map.get(&cg) {
250 wh.cond = Some(Rc::clone(new_cg));
251 }
252 }
253 self.rewrite_control(&mut wh.body);
255 }
256 ir::Control::Repeat(rep) => {
257 self.rewrite_control(&mut rep.body);
259 }
260 ir::Control::Invoke(inv) => self.rewrite_invoke(inv),
261 ir::Control::Static(s) => self.rewrite_static_control(s),
262 ir::Control::FSMEnable(_) => (),
263 }
264 }
265
266 pub fn rewrite(&self, comp: &mut ir::Component) {
268 comp.for_each_assignment(|assign| {
270 self.rewrite_assign(assign);
271 });
272 comp.for_each_static_assignment(|assign| {
273 self.rewrite_assign(assign);
274 });
275 self.rewrite_control(&mut RefCell::borrow_mut(
276 comp.control.borrow_mut(),
277 ));
278 }
279}