calyx_opt/passes/
static_fsm_opts.rs

1use crate::traversal::{
2    Action, ConstructVisitor, Named, ParseVal, PassOpt, VisResult, Visitor,
3};
4use calyx_ir::{self as ir, LibrarySignatures};
5use calyx_utils::CalyxResult;
6
7/// Adds assignments from a components `clk` port to every
8/// component that contains an input `clk` port.
9pub struct StaticFSMOpts {
10    one_hot_cutoff: u64,
11}
12
13impl Named for StaticFSMOpts {
14    fn name() -> &'static str {
15        "static-fsm-opts"
16    }
17
18    fn description() -> &'static str {
19        "Inserts attributes to optimize Static FSMs"
20    }
21
22    fn opts() -> Vec<PassOpt> {
23        vec![PassOpt::new(
24            "one-hot-cutoff",
25            "The upper limit on the number of states the static FSM must have before we pick binary \
26            encoding over one-hot. Defaults to 0 (i.e., always choose binary encoding)",
27            ParseVal::Num(0),
28            PassOpt::parse_num,
29        )]
30    }
31}
32
33impl ConstructVisitor for StaticFSMOpts {
34    fn from(ctx: &ir::Context) -> CalyxResult<Self> {
35        let opts = Self::get_opts(ctx);
36
37        Ok(StaticFSMOpts {
38            one_hot_cutoff: opts["one-hot-cutoff"].pos_num().unwrap(),
39        })
40    }
41
42    fn clear_data(&mut self) {}
43}
44
45impl Visitor for StaticFSMOpts {
46    fn start(
47        &mut self,
48        comp: &mut ir::Component,
49        _sigs: &LibrarySignatures,
50        _comps: &[ir::Component],
51    ) -> VisResult {
52        comp.get_static_groups_mut().iter_mut().for_each(|sgroup| {
53            let sgroup_latency = sgroup.borrow().get_latency();
54            // If static group's latency is less than the cutoff, encode as a
55            // one-hot FSM.
56            if sgroup_latency < self.one_hot_cutoff {
57                sgroup
58                    .borrow_mut()
59                    .attributes
60                    .insert(ir::BoolAttr::OneHot, 1);
61            }
62        });
63
64        // we don't need to traverse control
65        Ok(Action::Stop)
66    }
67}