calyx_opt/passes_experimental/
simplify_if_comb.rs1use crate::traversal::{Action, ConstructVisitor, Named, VisResult, Visitor};
2use calyx_ir::{self as ir, LibrarySignatures, Rewriter, rewriter::RewriteMap};
3use calyx_utils::CalyxResult;
4use itertools::Itertools;
5
6pub struct SimplifyIfComb {}
36
37impl Named for SimplifyIfComb {
38 fn name() -> &'static str {
39 "simplify-if-comb"
40 }
41
42 fn description() -> &'static str {
43 "Transform `if` with comb groups into `if` with continuous assignments when there is only one enable in the `then` block and there is no `else` block."
44 }
45
46 fn opts() -> Vec<crate::traversal::PassOpt> {
47 vec![]
48 }
49}
50
51impl ConstructVisitor for SimplifyIfComb {
52 fn from(_ctx: &ir::Context) -> CalyxResult<Self>
53 where
54 Self: Sized + Named,
55 {
56 Ok(SimplifyIfComb {})
57 }
58
59 fn clear_data(&mut self) {}
60}
61
62impl Visitor for SimplifyIfComb {
63 fn finish_if(
64 &mut self,
65 s: &mut calyx_ir::If,
66 comp: &mut calyx_ir::Component,
67 sigs: &LibrarySignatures,
68 _comps: &[calyx_ir::Component],
69 ) -> VisResult {
70 let mut builder = ir::Builder::new(comp, sigs);
71 let mut rewrite_map = RewriteMap::new();
72 let mut new_continuous_assignments = Vec::new();
73
74 let Some(cond_group_ref) = &s.cond else {
75 return Ok(Action::Continue);
76 };
77 for cond_group_asgn in &cond_group_ref.borrow().assignments {
79 if let calyx_ir::PortParent::Cell(c) =
80 &cond_group_asgn.dst.borrow().parent
81 {
82 let c_ref = c.upgrade();
83 let c_name = c_ref.borrow().name();
84 if !rewrite_map.contains_key(&c_name)
85 && let ir::CellType::Primitive {
86 name,
87 param_binding,
88 ..
89 } = &c_ref.borrow().prototype
90 {
91 let new_cell = builder.add_primitive(
92 c_name,
93 *name,
94 ¶m_binding.iter().map(|(_, v)| *v).collect_vec(),
95 );
96 rewrite_map.insert(c_name, new_cell);
97 }
98 }
99 }
100
101 for cond_group_asgn in &cond_group_ref.borrow().assignments {
103 let new_asgn = cond_group_asgn.clone();
104 new_continuous_assignments.push(new_asgn);
105 }
106
107 let rewrite = Rewriter {
108 cell_map: rewrite_map,
109 ..Default::default()
110 };
111 for asgn in new_continuous_assignments.iter_mut() {
112 rewrite.rewrite_assign(asgn);
113 comp.continuous_assignments.push(asgn.clone());
114 }
115
116 let mut new_if = calyx_ir::Control::if_(
120 s.port.clone(),
121 None,
122 Box::new(s.tbranch.take_control()),
123 Box::new(s.fbranch.take_control()),
124 );
125 rewrite.rewrite_control(&mut new_if);
126 Ok(Action::Change(Box::new(new_if)))
127 }
128}