From 9bd2b6ed6a3891fa489ab3082706266eab8c35a6 Mon Sep 17 00:00:00 2001 From: Parth Sarkar Date: Mon, 4 Nov 2024 18:43:21 -0500 Subject: [PATCH] Started function and implemented printer for fsm - started indexing states from 1 (because of transition from 0 -> 1) - need to enable fsms and register transitions within fsm - need to replace control node with fsm in each function --- calyx-ir/src/builder.rs | 2 +- calyx-ir/src/component.rs | 5 ++ calyx-ir/src/printer.rs | 56 ++++++++++++++++++++++ calyx-ir/src/structure.rs | 29 +++-------- calyx-opt/src/passes/dyn_fsm_allocation.rs | 41 ++++++++++++++-- 5 files changed, 104 insertions(+), 29 deletions(-) diff --git a/calyx-ir/src/builder.rs b/calyx-ir/src/builder.rs index 623b149e8..fa32ed447 100644 --- a/calyx-ir/src/builder.rs +++ b/calyx-ir/src/builder.rs @@ -80,7 +80,7 @@ impl<'a> Builder<'a> { let fsm = ir::rrc(ir::FSM::new(name)); // Fill in the ports of the FSM with default wires - for (name, width) in &[("go", 1), ("done", 1)] { + for (name, width) in &[("go", 1), ("done", 1), ("state", 1)] { let hole = ir::rrc(ir::Port { name: ir::Id::from(*name), width: *width, diff --git a/calyx-ir/src/component.rs b/calyx-ir/src/component.rs index 323ae5f3b..71573ab25 100644 --- a/calyx-ir/src/component.rs +++ b/calyx-ir/src/component.rs @@ -156,6 +156,11 @@ impl Component { &self.groups } + /// get the component's fsms + pub fn get_fsms(&self) -> &IdList { + &self.fsms + } + /// gets the component's static groups pub fn get_static_groups(&self) -> &IdList { &self.static_groups diff --git a/calyx-ir/src/printer.rs b/calyx-ir/src/printer.rs index 9ad499782..9cbc09869 100644 --- a/calyx-ir/src/printer.rs +++ b/calyx-ir/src/printer.rs @@ -239,6 +239,7 @@ impl Printer { Self::write_static_group(&group.borrow(), 4, f)?; writeln!(f)?; } + for fsm in comp.get_fsms().iter() {} for comb_group in comp.comb_groups.iter() { Self::write_comb_group(&comb_group.borrow(), 4, f)?; writeln!(f)?; @@ -426,6 +427,61 @@ impl Printer { write!(f, "{}}}", " ".repeat(indent_level)) } + /// Formt and write an FSM + pub fn write_fsm( + fsm: &ir::FSM, + indent_level: usize, + f: &mut F, + ) -> io::Result<()> { + write!(f, "{}", " ".repeat(indent_level))?; + write!(f, "fsm {}", fsm.name().id)?; + if !fsm.attributes.is_empty() { + write!(f, "{}", Self::format_attributes(&fsm.attributes))?; + } + writeln!(f, " {{")?; + for (i, (assigns, trans)) in + fsm.assignments.iter().zip(&fsm.transitions).enumerate() + { + // WRITE ASSIGNMENTS + write!(f, "{}", " ".repeat(indent_level + 2))?; + write!(f, "{} : ", i + 1)?; + match assigns.is_empty() { + true => { + // skip directly to transitions section + write!(f, "{{")?; + write!(f, "}} ")?; + write!(f, "=> ")?; + } + false => { + writeln!(f, "{{")?; + for assign in assigns { + Self::write_assignment(assign, indent_level + 4, f)?; + writeln!(f)?; + } + write!(f, "{}", " ".repeat(indent_level + 2))?; + write!(f, "}} => ")?; + } + } + + // WRITE TRANSITIONS + match trans { + ir::Transition::Unconditional(s) => { + writeln!(f, "{},", s)?; + } + ir::Transition::Conditional(cond_dsts) => { + writeln!(f, "{{")?; + for (g, dst) in cond_dsts.iter() { + write!(f, "{}", " ".repeat(indent_level + 4))?; + writeln!(f, "{} ? {} :", Self::guard_str(g), dst)?; + } + write!(f, "{}", " ".repeat(indent_level + 2))?; + writeln!(f, "}},")?; + } + } + } + write!(f, "{}}}", " ".repeat(indent_level)) + } + /// Format and write a static group. pub fn write_static_group( group: &ir::StaticGroup, diff --git a/calyx-ir/src/structure.rs b/calyx-ir/src/structure.rs index 1af6643da..6c4c99bcd 100644 --- a/calyx-ir/src/structure.rs +++ b/calyx-ir/src/structure.rs @@ -601,34 +601,14 @@ pub enum State { #[derive(Debug)] #[cfg_attr(feature = "serialize", derive(serde::Serialize))] pub enum Transition { - Unconditional(State), - Conditional(Vec<(Guard, State)>), + Unconditional(u64), + Conditional(Vec<(Guard, u64)>), } impl Transition { - pub fn new_uncond(s: State) -> Self { + pub fn new_uncond(s: u64) -> Self { Self::Unconditional(s) } - - pub fn new_cond(conds: Vec<(Guard, State)>) -> Self { - Self::Conditional(conds) - } -} - -#[derive(Debug)] -#[cfg_attr(feature = "serialize", derive(serde::Serialize))] -pub struct Branch { - /// Originating state of the FSM transition - src: State, - - /// Optionally conditional destination states of the transition - dsts: Transition, -} - -impl Branch { - pub fn new(src: State, dsts: Transition) -> Self { - Branch { src, dsts } - } } /// A Group of assignments that perform a logical action. @@ -833,6 +813,8 @@ impl CombGroup { pub struct FSM { /// Name of this construct pub(super) name: Id, + /// Number of states in this FSM + pub num_states: u64, /// Attributes for this FSM pub attributes: Attributes, /// State indexes into assignments that are supposed to be enabled at that state @@ -853,6 +835,7 @@ impl FSM { pub fn new(name: Id) -> Self { Self { name, + num_states: 0, assignments: vec![], transitions: vec![], wires: SmallVec::new(), diff --git a/calyx-opt/src/passes/dyn_fsm_allocation.rs b/calyx-opt/src/passes/dyn_fsm_allocation.rs index 277cb7946..de5f9415c 100644 --- a/calyx-opt/src/passes/dyn_fsm_allocation.rs +++ b/calyx-opt/src/passes/dyn_fsm_allocation.rs @@ -394,7 +394,38 @@ impl<'b, 'a> Schedule<'b, 'a> { } fn realize_fsm(self, dump_fsm: bool) -> RRC { - ir::rrc(ir::FSM::new(Id::new("fsm"))) + // STATES ARE NOW INDEXED FROM 1 + // ensure schedule is valid + self.validate(); + + // compute final state and fsm_size, and register initial fsm + let last_state = self.last_state(); + let fsm_size = get_bit_width_from(last_state + 1); + let fsm = self.builder.add_fsm("fsm"); + + // register group enables that are dependent on fsm state as continuous assignments + let continuous_enables = self + .enables + .into_iter() + .sorted_by(|(k1, _), (k2, _)| k1.cmp(k2)) + .flat_map(|(state, mut assigns_to_enable)| { + let state_const = self.builder.add_constant(state, fsm_size); + let state_guard = guard!(fsm["state"] == state_const["out"]); + assigns_to_enable.iter_mut().for_each(|assign| { + assign.guard.update(|g| g.and(state_guard.clone())) + }); + assigns_to_enable + }) + .collect_vec(); + + self.builder + .component + .continuous_assignments + .extend(continuous_enables); + + // add + + fsm } } @@ -669,7 +700,7 @@ impl Schedule<'_, '_> { seq: &ir::Seq, early_transitions: bool, ) -> CalyxResult<()> { - let first_state = (0, ir::Guard::True); + let first_state = (1, ir::Guard::True); // We create an empty first state in case the control program starts with // a branch (if, while). // If the program doesn't branch, then the initial state is merged into @@ -686,7 +717,7 @@ impl Schedule<'_, '_> { if_stmt: &ir::If, early_transitions: bool, ) -> CalyxResult<()> { - let first_state = (0, ir::Guard::True); + let first_state = (1, ir::Guard::True); // We create an empty first state in case the control program starts with // a branch (if, while). // If the program doesn't branch, then the initial state is merged into @@ -703,7 +734,7 @@ impl Schedule<'_, '_> { while_stmt: &ir::While, early_transitions: bool, ) -> CalyxResult<()> { - let first_state = (0, ir::Guard::True); + let first_state = (1, ir::Guard::True); // We create an empty first state in case the control program starts with // a branch (if, while). // If the program doesn't branch, then the initial state is merged into @@ -743,7 +774,7 @@ impl Schedule<'_, '_> { con: &ir::Control, early_transitions: bool, ) -> CalyxResult<()> { - let first_state = (0, ir::Guard::True); + let first_state = (1, ir::Guard::True); // We create an empty first state in case the control program starts with // a branch (if, while). // If the program doesn't branch, then the initial state is merged into