calyx_opt/passes/
go_insertion.rs

1use crate::traversal::{Action, Named, VisResult, Visitor};
2use calyx_ir::guard;
3use calyx_ir::{self as ir, LibrarySignatures};
4
5#[derive(Default)]
6/// Add the group's `go` signal into the guards of all non-hole assignments
7/// of this group.
8///
9/// For example, the pass transforms this Calyx program:
10/// ```
11/// group foo {
12///     x.in = cond ? 32'd1;
13///     foo[done] = reg.done;
14/// }
15/// ```
16/// into:
17/// ```
18/// group foo {
19///     x.in = cond & foo[go] ? 32'd1;
20///     foo[done] = reg.done;
21/// }
22/// ```
23pub struct GoInsertion {}
24
25impl Named for GoInsertion {
26    fn name() -> &'static str {
27        "go-insertion"
28    }
29
30    fn description() -> &'static str {
31        "Inserts `go` signals into the guards of a group's non-hole assignments"
32    }
33}
34
35impl Visitor for GoInsertion {
36    fn start(
37        &mut self,
38        comp: &mut ir::Component,
39        _c: &LibrarySignatures,
40        _comps: &[ir::Component],
41    ) -> VisResult {
42        // assume static groups is empty
43        for group in comp.get_groups().iter() {
44            let group_go = guard!(group["go"]);
45            // Detach the group's assignments so we can drop the mutable access to it.
46            let mut group_assigns =
47                group.borrow_mut().assignments.drain(..).collect::<Vec<_>>();
48            for assign in group_assigns.iter_mut() {
49                let dst = assign.dst.borrow();
50                if !(dst.is_hole() && dst.name == "done") {
51                    *assign.guard &= group_go.clone();
52                }
53            }
54            group.borrow_mut().assignments = group_assigns;
55        }
56
57        // This pass doesn't modify any control.
58        Ok(Action::Stop)
59    }
60}