cmtc/passes/
fsmgen.rs

1use super::*;
2use crate::{
3  BodyOp, BranchOp, Cmp, ForOp, Module, Op, ParOp, Prim, Rule, TypedLit,
4};
5
6pub mod pass;
7pub use pass::*;
8
9mod templates;
10
11impl Visitor for FSMGenPass {
12  fn name() -> &'static str {
13    "FSMGen"
14  }
15
16  /// tb module should have no fsm
17  fn skip_tb() -> bool {
18    true
19  }
20
21  fn before_visit_rules(
22    &mut self,
23    data: &mut VisitorData,
24  ) -> anyhow::Result<()> {
25    self.cur_module_name = data.module.name.clone();
26    self.step_cnt = 0;
27    self.seq_cnt = 0;
28    self.par_cnt = 0;
29    self.branch_cnt = 0;
30    self.for_cnt = 0;
31    self.pipeline_cnt = 0;
32    Ok(())
33  }
34
35  fn visit_rule_impl(
36    &mut self,
37    data: &mut VisitorData,
38  ) -> Result<(Vec<crate::Rule>, Vec<crate::RuleRel>), anyhow::Error> {
39    let rule = data.take_rule();
40    if matches!(rule.timing, ir::RuleTiming::FSM) {
41      assert!(rule.ops.len() == 1, "FSM rule can only have one op!");
42      let fsm = self.visit_op(rule.ops.first().unwrap());
43      let rules = self.gen_rules(fsm, data, rule);
44      self.fsm_cnt += 1;
45      Ok((rules, vec![]))
46    } else if matches!(rule.timing, ir::RuleTiming::Pipeline) {
47      let fsm = self.visit_pipeline(&rule.ops);
48      let rules = self.gen_rules(fsm, data, rule);
49      self.fsm_cnt += 1;
50      Ok((rules, vec![]))
51    } else {
52      Ok((vec![rule], vec![]))
53    }
54  }
55
56  fn after_visit_rules(
57    &mut self,
58    data: &mut VisitorData,
59  ) -> anyhow::Result<()> {
60    for (i, s) in self.top_fsms.drain(..).enumerate() {
61      data.module.add_instance(format!("GEN_fsm_{i}"), s);
62    }
63    for (lhs, rhs) in self.cfs.drain(..) {
64      data.module.add_method_rel(cmtrs::MethodRel::CF, lhs, rhs);
65    }
66    Ok(())
67  }
68
69  fn after_pass(&mut self, circuit: &mut crate::Circuit) -> anyhow::Result<()> {
70    for module in self.gen_modules.drain(..) {
71      circuit.add_module(module);
72    }
73    Ok(())
74  }
75}