calyx_opt/passes_experimental/
external_to_ref.rs

1use crate::traversal::{
2    Action, ConstructVisitor, Named, ParseVal, PassOpt, VisResult, Visitor,
3};
4use calyx_ir::{self as ir, GetAttributes, LibrarySignatures};
5use calyx_utils::CalyxResult;
6
7/// Turns memory cell primitives with the `@external(1)` attribute into
8/// `ref` memory cells without the `@external` attribute.
9pub struct ExternalToRef {
10    /// whether to actually have this pass take effect
11    active: bool,
12}
13
14impl Named for ExternalToRef {
15    fn name() -> &'static str {
16        "external-to-ref"
17    }
18
19    fn description() -> &'static str {
20        "Turn memory cells marked with `@external(1) into `ref` memory cells."
21    }
22
23    fn opts() -> Vec<PassOpt> {
24        vec![PassOpt::new(
25            "activate",
26            "activate this pass. this pass has a hard-coded order, and is thus off by default.",
27            ParseVal::Bool(false),
28            PassOpt::parse_bool,
29        )]
30    }
31}
32
33impl ConstructVisitor for ExternalToRef {
34    fn from(ctx: &ir::Context) -> CalyxResult<Self>
35    where
36        Self: Sized,
37    {
38        let opts = Self::get_opts(ctx);
39        let external_to_ref = ExternalToRef {
40            active: opts["activate"].bool(),
41        };
42        Ok(external_to_ref)
43    }
44
45    fn clear_data(&mut self) {}
46}
47
48impl Visitor for ExternalToRef {
49    fn start(
50        &mut self,
51        comp: &mut ir::Component,
52        _ctx: &LibrarySignatures,
53        _comps: &[ir::Component],
54    ) -> VisResult {
55        if self.active {
56            // Iterate over each cell in the component
57            for cell in comp.cells.iter() {
58                let mut cell_ref = cell.borrow_mut();
59                if cell_ref.get_attributes().has(ir::BoolAttr::External) {
60                    // Change the cell type to `ref` and remove the external attribute
61                    cell_ref
62                        .get_mut_attributes()
63                        .remove(ir::BoolAttr::External);
64                    cell_ref.set_reference(true);
65                }
66            }
67        }
68        // Continue visiting other nodes in the AST
69        Ok(Action::Continue)
70    }
71}