calyx_opt/passes/
wire_inliner.rs1use crate::traversal::{Action, Named, VisResult, Visitor};
2use calyx_ir as ir;
3use ir::{build_assignments, guard, structure, LibrarySignatures};
4use ir::{Nothing, RRC};
5use itertools::Itertools;
6use std::{collections::HashMap, rc::Rc};
7
8#[derive(Default)]
9pub struct WireInliner;
12
13type HoleMapping = HashMap<ir::Id, (RRC<ir::Cell>, RRC<ir::Cell>)>;
14
15impl Named for WireInliner {
16    fn name() -> &'static str {
17        "wire-inliner"
18    }
19
20    fn description() -> &'static str {
21        "inlines holes using wires"
22    }
23}
24
25fn rewrite_assign(map: &HoleMapping, assign: &mut ir::Assignment<Nothing>) {
26    let rewrite = |port: &RRC<ir::Port>| -> Option<RRC<ir::Cell>> {
27        if let ir::PortParent::Group(g) = &port.borrow().parent {
28            let (go, done) = &map[&g.upgrade().borrow().name()];
29            let cell = if port.borrow().name == "go" { go } else { done };
30            Some(Rc::clone(cell))
31        } else {
32            None
33        }
34    };
35
36    if let Some(cell) = rewrite(&assign.dst) {
37        assign.dst = cell.borrow().get("in");
38    }
39    if let Some(cell) = rewrite(&assign.src) {
40        assign.src = cell.borrow().get("out");
41    }
42    assign.guard.for_each(&mut |port| {
43        rewrite(&port).map(|cell| ir::Guard::port(cell.borrow().get("out")))
44    });
45}
46
47impl Visitor for WireInliner {
48    fn start(
49        &mut self,
50        comp: &mut ir::Component,
51        sigs: &LibrarySignatures,
52        _comps: &[ir::Component],
53    ) -> VisResult {
54        let control_ref = Rc::clone(&comp.control);
55        let control = control_ref.borrow();
56        match &*control {
62            ir::Control::Enable(data) => {
63                let this = Rc::clone(&comp.signature);
64                let mut builder = ir::Builder::new(comp, sigs);
65                let group = &data.group;
66
67                structure!(builder;
68                    let one = constant(1, 1);
69                );
70                let group_done = guard!(group["done"]);
71                let assigns = build_assignments!(builder;
72                    group["go"] = ? this["go"];
73                    this["done"] = group_done ? one["out"];
74                );
75                comp.continuous_assignments.extend(assigns);
76            }
77            ir::Control::Empty(_) => {}
78            _ => {
79                return Err(calyx_utils::Error::malformed_control(format!(
80                    "{}: Structure has more than one group",
81                    Self::name()
82                )));
83            }
84        }
85
86        let groups = comp.get_groups_mut().drain().collect_vec();
88        let mut builder = ir::Builder::new(comp, sigs);
89        let hole_map: HoleMapping = groups
91            .iter()
92            .map(|gr| {
93                let name = gr.borrow().name();
94                let go = builder.add_primitive(
95                    format!("{}_go", name),
96                    "std_wire",
97                    &[1],
98                );
99                let done = builder.add_primitive(
100                    format!("{}_done", name),
101                    "std_wire",
102                    &[1],
103                );
104                (name, (go, done))
105            })
106            .collect();
107
108        groups.iter().for_each(|gr| {
110            let mut assigns =
115                gr.borrow_mut().assignments.drain(..).collect_vec();
116            assigns
117                .iter_mut()
118                .for_each(|asgn| rewrite_assign(&hole_map, asgn));
119            gr.borrow_mut().assignments = assigns;
120        });
121
122        comp.continuous_assignments
123            .iter_mut()
124            .for_each(|assign| rewrite_assign(&hole_map, assign));
125
126        let mut group_assigns = groups
127            .into_iter()
128            .flat_map(|g| g.borrow_mut().assignments.drain(..).collect_vec())
129            .collect_vec();
130
131        comp.continuous_assignments.append(&mut group_assigns);
132
133        Ok(Action::change(ir::Control::empty()))
135    }
136}