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 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}