calyx_opt/passes/
compile_repeat.rs1use crate::traversal::{Action, Named, VisResult, Visitor};
2use calyx_ir::structure;
3use calyx_ir::{self as ir, LibrarySignatures};
4use calyx_utils::math::bits_needed_for;
5
6use ir::{build_assignments, guard};
7#[derive(Default)]
10pub struct CompileRepeat;
11
12impl Named for CompileRepeat {
13 fn name() -> &'static str {
14 "compile-repeat"
15 }
16
17 fn description() -> &'static str {
18 "Rewrites repeat statements into while loops"
19 }
20}
21
22impl Visitor for CompileRepeat {
23 fn finish_repeat(
24 &mut self,
25 s: &mut ir::Repeat,
26 comp: &mut ir::Component,
27 ctx: &LibrarySignatures,
28 _comps: &[ir::Component],
29 ) -> VisResult {
30 let num_repeats = s.num_repeats;
31 if num_repeats == 0 {
32 Ok(Action::change(ir::Control::empty()))
34 } else if num_repeats == 1 {
35 Ok(Action::change(s.body.take_control()))
37 } else {
38 let mut builder = ir::Builder::new(comp, ctx);
40 let idx_size = bits_needed_for(num_repeats + 1);
41 structure!( builder;
42 let idx = prim std_reg(idx_size);
44 let cond_reg = prim std_reg(1);
46 let adder = prim std_add(idx_size);
47 let lt = prim std_lt(idx_size);
48 let const_zero = constant(0, idx_size);
49 let const_one = constant(1, idx_size);
50 let num_repeats = constant(num_repeats, idx_size);
51 let signal_on = constant(1,1);
52 );
53 let regs_done: ir::Guard<ir::Nothing> =
55 guard!(cond_reg["done"] & idx["done"]);
56 let init_group = builder.add_group("init_repeat");
58 let init_assigns = build_assignments!(
59 builder;
60 idx["write_en"] = ? signal_on["out"];
62 idx["in"] = ? const_zero["out"];
63 cond_reg["write_en"] = ? signal_on["out"];
64 cond_reg["in"] = ? signal_on["out"];
65 init_group["done"] = regs_done ? signal_on["out"];
66 )
67 .to_vec();
68 init_group.borrow_mut().assignments = init_assigns;
69 init_group
70 .borrow_mut()
71 .attributes
72 .insert(ir::NumAttr::Promotable, 1);
73 let incr_group = builder.add_group("incr_repeat");
77 let idx_incr_assigns = build_assignments!(
78 builder;
79 adder["left"] = ? idx["out"];
80 adder["right"] = ? const_one["out"];
81 lt["left"] = ? adder["out"];
82 lt["right"] = ? num_repeats["out"];
83 cond_reg["write_en"] = ? signal_on["out"];
84 cond_reg["in"] = ? lt["out"];
85 idx["write_en"] = ? signal_on["out"];
86 idx["in"] = ? adder["out"];
87 incr_group["done"] = regs_done ? signal_on["out"];
88 )
89 .to_vec();
90 incr_group.borrow_mut().assignments = idx_incr_assigns;
91 incr_group
92 .borrow_mut()
93 .attributes
94 .insert(ir::NumAttr::Promotable, 1);
95 let while_body = ir::Control::seq(vec![
98 s.body.take_control(),
99 ir::Control::enable(incr_group),
100 ]);
101 let while_loop = ir::Control::while_(
102 cond_reg.borrow().get("out"),
103 None,
104 Box::new(while_body),
105 );
106 let while_seq = ir::Control::Seq(ir::Seq {
107 stmts: vec![ir::Control::enable(init_group), while_loop],
108 attributes: std::mem::take(&mut s.attributes),
109 });
110 Ok(Action::change(while_seq))
111 }
112 }
113}