calyx_opt/passes/
constant_port_prop.rs1use crate::traversal::{Action, Named, VisResult, Visitor};
2use calyx_ir::{self as ir, LibrarySignatures};
3use std::collections::{HashMap, HashSet};
4
5#[derive(Debug, Default)]
27pub struct ConstantPortProp {
28 comb_groups_to_modify: HashMap<ir::Id, ir::Id>,
30 comb_groups_used_elsewhere: HashSet<ir::Id>,
34}
35
36impl Named for ConstantPortProp {
37 fn name() -> &'static str {
38 "constant-port-prop"
39 }
40
41 fn description() -> &'static str {
42 "propagates constants when port values can be inferred"
43 }
44}
45
46impl Visitor for ConstantPortProp {
47 fn invoke(
48 &mut self,
49 s: &mut calyx_ir::Invoke,
50 _comp: &mut calyx_ir::Component,
51 _sigs: &LibrarySignatures,
52 _comps: &[calyx_ir::Component],
53 ) -> VisResult {
54 if let Some(cg) = &s.comb_group {
55 let cg_name = cg.borrow().name();
56 let cell_name = s.comp.borrow().name();
57 if let Some(registered_cell_name) =
58 self.comb_groups_to_modify.get(&cg_name)
59 {
60 if *registered_cell_name != cell_name {
61 self.comb_groups_used_elsewhere.insert(cg_name);
63 }
64 } else {
65 self.comb_groups_to_modify.insert(cg_name, cell_name);
67 }
68 }
69 Ok(Action::Continue)
70 }
71
72 fn start_while(
73 &mut self,
74 s: &mut calyx_ir::While,
75 _comp: &mut calyx_ir::Component,
76 _sigs: &LibrarySignatures,
77 _comps: &[calyx_ir::Component],
78 ) -> VisResult {
79 if let Some(comb_group) = &s.cond {
80 self.comb_groups_used_elsewhere
81 .insert(comb_group.borrow().name());
82 }
83 Ok(Action::Continue)
84 }
85
86 fn start_if(
87 &mut self,
88 s: &mut calyx_ir::If,
89 _comp: &mut calyx_ir::Component,
90 _sigs: &LibrarySignatures,
91 _comps: &[calyx_ir::Component],
92 ) -> VisResult {
93 if let Some(comb_group) = &s.cond {
94 self.comb_groups_used_elsewhere
95 .insert(comb_group.borrow().name());
96 }
97 Ok(Action::Continue)
98 }
99
100 fn finish(
101 &mut self,
102 comp: &mut calyx_ir::Component,
103 sigs: &LibrarySignatures,
104 _comps: &[calyx_ir::Component],
105 ) -> VisResult {
106 let mut builder = ir::Builder::new(comp, sigs);
107 let one = builder.add_constant(1, 1);
108 let zero = builder.add_constant(0, 1);
109 for comb_group_ref in comp.comb_groups.iter().filter(|item| {
111 !self
112 .comb_groups_used_elsewhere
113 .contains(&item.borrow().name())
114 }) {
115 let mut comb_group = comb_group_ref.borrow_mut();
117 let comb_group_name = comb_group.name();
118 if let Some(cell_name) =
119 self.comb_groups_to_modify.get(&comb_group_name)
120 {
121 let mut modified_asgns =
122 std::mem::take(&mut comb_group.assignments);
123 for asgn in modified_asgns.iter_mut() {
124 asgn.for_each_port(|port_ref| {
125 let mut res = None;
126 let port = port_ref.borrow();
127 if let ir::PortParent::Cell(cell_wref) = &port.parent {
128 if cell_wref.upgrade().borrow().name() == cell_name
129 && port.name == "done"
130 {
131 res = Some(zero.borrow().get("out"));
133 } else if cell_wref.upgrade().borrow().name()
134 == cell_name
135 && port.name == "go"
136 {
137 res = Some(one.borrow().get("out"));
139 }
140 }
141 res
142 });
143 }
144 comb_group.assignments = modified_asgns;
145 }
146 }
147
148 Ok(Action::Continue)
149 }
150}