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}