1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90
use crate::traversal::{Action, Named, VisResult, Visitor};
use calyx_ir::{self as ir, Component, Control, LibrarySignatures};
use calyx_ir::{build_assignments, structure};
use std::rc::Rc;
#[derive(Default)]
/// Compiles away all [`ir::Empty`](calyx_ir::Empty) statements into an
/// [`ir::Enable`](calyx_ir::Enable).
///
/// The generated program enables the following group:
/// ```calyx
/// cells {
/// @generated empty_reg = std_reg(1);
/// }
///
/// group _empty {
/// empty_reg.write_en = 1'd1;
/// empty_reg.in = 1'd1;
/// _empty["done"] = empty_reg.done;
/// }
/// ```
pub struct CompileEmpty {
// Name of the empty group if it has been created.
group_name: Option<ir::Id>,
}
impl Named for CompileEmpty {
fn name() -> &'static str {
"compile-empty"
}
fn description() -> &'static str {
"Rewrites empty control to invocation to empty group"
}
}
impl Visitor for CompileEmpty {
fn empty(
&mut self,
_s: &mut ir::Empty,
comp: &mut Component,
sigs: &LibrarySignatures,
_comps: &[ir::Component],
) -> VisResult {
let group_ref = match self.group_name {
Some(g) => comp.find_group(g).unwrap(),
None => {
let mut builder = ir::Builder::new(comp, sigs);
// Build the new group
let empty_group = builder.add_group("_empty");
empty_group
.borrow_mut()
.attributes
.insert(ir::NumAttr::Static, 1);
// Add this signal empty_group[done] = 1'd1;
structure!(builder;
let signal_on = constant(1, 1);
let empty_reg = prim std_reg(1);
);
let assigns = build_assignments!(builder;
empty_reg["write_en"] = ? signal_on["out"];
empty_reg["in"] = ? signal_on["out"];
empty_group["done"] = ? empty_reg["done"];
);
empty_group.borrow_mut().assignments.extend(assigns);
// Register the name of the group to the pass
self.group_name = Some(empty_group.borrow().name());
empty_group
}
};
Ok(Action::change(Control::enable(Rc::clone(&group_ref))))
}
fn finish(
&mut self,
_comp: &mut Component,
_sigs: &LibrarySignatures,
_comps: &[ir::Component],
) -> VisResult {
// The empty group, if created, is only defined for this component.
// Deregister it before walking over another group.
self.group_name = None;
Ok(Action::Continue)
}
}