From 46dd5129771998981d09a04592523c0d01de1d3a Mon Sep 17 00:00:00 2001 From: Cynthia Shao Date: Thu, 4 Sep 2025 15:37:36 -0400 Subject: [PATCH 1/8] updating the static seq for all annotator possibilities --- .../src/passes_experimental/fsm_builder.rs | 65 ++++++++++++++----- 1 file changed, 49 insertions(+), 16 deletions(-) diff --git a/calyx/opt/src/passes_experimental/fsm_builder.rs b/calyx/opt/src/passes_experimental/fsm_builder.rs index e1fbb8c714..8809219708 100644 --- a/calyx/opt/src/passes_experimental/fsm_builder.rs +++ b/calyx/opt/src/passes_experimental/fsm_builder.rs @@ -135,23 +135,56 @@ impl StaticSchedule<'_, '_> { ) } } - ir::StaticControl::Seq(sseq) => ( - // For now, we'll automatically inline static seqs. - // Added support for more annotations will be coming in the future. - sseq.stmts.iter().fold( - transitions_to_curr, - |transitions_to_this_stmt, stmt| { - self.build_abstract( - stmt, - guard.clone(), - transitions_to_this_stmt, - looped_once_guard.clone(), + ir::StaticControl::Seq(sseq) => { + (if is_acyclic(sseq) { + if is_inline(sseq) { + // @NUM_STATES(n) @ACYCLIC @INLINE + ( + sseq.stmts.iter().fold( + transitions_to_curr, + |transitions_to_this_stmt, stmt| { + self.build_abstract( + stmt, + guard.clone(), + transitions_to_this_stmt, + looped_once_guard.clone(), + ) + .0 + }, + ), + None, ) - .0 - }, - ), - None, - ), + } else { + todo!() + } + } else { + if is_inline(sseq) { + // @NUM_STATES(n) @INLINE + // may be incorrect for now, must think about what back edges might be possible for a static seq + ( + sseq.stmts.iter().fold( + transitions_to_curr, + |transitions_to_this_stmt, stmt| { + self.build_abstract( + stmt, + guard.clone(), + transitions_to_this_stmt, + looped_once_guard.clone(), + ) + .0 + }, + ), + None, + ) + } else if is_offload(sseq) { + // @NUM_STATES(1) @OFFLOAD + todo!() + } else { + // cyclic static seqs are not possible + unreachable!() + } + }) + } ir::StaticControl::Repeat(srep) => { // Matching for the `@ACYCLIC` attribute coming soon. if is_unroll(srep) { From 7b4977ed64559bd417bc862fd4056c778e16ef76 Mon Sep 17 00:00:00 2001 From: Cynthia Shao Date: Thu, 4 Sep 2025 15:39:01 -0400 Subject: [PATCH 2/8] fixed unecessary parentheses --- calyx/opt/src/passes_experimental/fsm_builder.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/calyx/opt/src/passes_experimental/fsm_builder.rs b/calyx/opt/src/passes_experimental/fsm_builder.rs index 8809219708..334cee3fe4 100644 --- a/calyx/opt/src/passes_experimental/fsm_builder.rs +++ b/calyx/opt/src/passes_experimental/fsm_builder.rs @@ -136,7 +136,7 @@ impl StaticSchedule<'_, '_> { } } ir::StaticControl::Seq(sseq) => { - (if is_acyclic(sseq) { + if is_acyclic(sseq) { if is_inline(sseq) { // @NUM_STATES(n) @ACYCLIC @INLINE ( @@ -183,7 +183,7 @@ impl StaticSchedule<'_, '_> { // cyclic static seqs are not possible unreachable!() } - }) + } } ir::StaticControl::Repeat(srep) => { // Matching for the `@ACYCLIC` attribute coming soon. From 1bf490a0453f3d47b2d15d01296e8ab19491ada4 Mon Sep 17 00:00:00 2001 From: Cynthia Shao Date: Thu, 4 Sep 2025 16:10:31 -0400 Subject: [PATCH 3/8] finished enumerating all the possibilities for static scheduels --- .../src/passes_experimental/fsm_builder.rs | 132 +++++++++++------- 1 file changed, 79 insertions(+), 53 deletions(-) diff --git a/calyx/opt/src/passes_experimental/fsm_builder.rs b/calyx/opt/src/passes_experimental/fsm_builder.rs index 334cee3fe4..312ac99224 100644 --- a/calyx/opt/src/passes_experimental/fsm_builder.rs +++ b/calyx/opt/src/passes_experimental/fsm_builder.rs @@ -136,58 +136,55 @@ impl StaticSchedule<'_, '_> { } } ir::StaticControl::Seq(sseq) => { - if is_acyclic(sseq) { - if is_inline(sseq) { - // @NUM_STATES(n) @ACYCLIC @INLINE - ( - sseq.stmts.iter().fold( - transitions_to_curr, - |transitions_to_this_stmt, stmt| { - self.build_abstract( - stmt, - guard.clone(), - transitions_to_this_stmt, - looped_once_guard.clone(), - ) - .0 - }, - ), - None, - ) - } else { - todo!() - } + if is_acyclic(sseq) && is_inline(sseq) { + // @NUM_STATES(n) @ACYCLIC @INLINE + ( + sseq.stmts.iter().fold( + transitions_to_curr, + |transitions_to_this_stmt, stmt| { + self.build_abstract( + stmt, + guard.clone(), + transitions_to_this_stmt, + looped_once_guard.clone(), + ) + .0 + }, + ), + None, + ) + } else if is_inline(sseq) { + // @NUM_STATES(n) @INLINE + // may be incorrect for now, must think about what back edges might be possible for a static seq + ( + sseq.stmts.iter().fold( + transitions_to_curr, + |transitions_to_this_stmt, stmt| { + self.build_abstract( + stmt, + guard.clone(), + transitions_to_this_stmt, + looped_once_guard.clone(), + ) + .0 + }, + ), + None, + ) + } else if is_offload(sseq) { + // @NUM_STATES(1) @OFFLOAD + todo!() } else { - if is_inline(sseq) { - // @NUM_STATES(n) @INLINE - // may be incorrect for now, must think about what back edges might be possible for a static seq - ( - sseq.stmts.iter().fold( - transitions_to_curr, - |transitions_to_this_stmt, stmt| { - self.build_abstract( - stmt, - guard.clone(), - transitions_to_this_stmt, - looped_once_guard.clone(), - ) - .0 - }, - ), - None, - ) - } else if is_offload(sseq) { - // @NUM_STATES(1) @OFFLOAD - todo!() - } else { - // cyclic static seqs are not possible - unreachable!() - } + // cyclic static seqs are not possible + // we must have at least one `attr` annotation + unreachable!( + "`build_abstract` encountered a node without any annotations." + ) } } ir::StaticControl::Repeat(srep) => { - // Matching for the `@ACYCLIC` attribute coming soon. - if is_unroll(srep) { + if is_acyclic(srep) && is_unroll(srep) { + // @ACYCLIC @UNROLL // In the encounter of a `@UNROLL` attribute, we'll want to create a state for each child. ( (0..srep.num_repeats).fold( @@ -205,21 +202,50 @@ impl StaticSchedule<'_, '_> { None, ) } else if is_offload(srep) { + // @NUM_STATES(1) @OFFLOAD + // In the case of offload, we'll want to create a state with a register to count the number of + // times to loop in place todo!() } else if is_inline(srep) { + // @NUM_STATES(n) @INLINE // In the case of inline, we'll want to assign as many states as children of this loop, // but create a register to count the amount of times looped, and assign // backward edges from the end to the beginning. todo!() } else { - todo!() + // we must have at least one `attr` annotation + unreachable!( + "`build_abstract` encountered a node without any annotations." + ) } } - ir::StaticControl::If(_sif) => { - todo!() + ir::StaticControl::If(sif) => { + if is_acyclic(sif) && is_inline(sif) { + // @NUM_STATES(n) @ACYCLIC @INLINE + todo!() + } else if is_offload(sif) { + // @NUM_STATES(1) @OFFLOAD + todo!() + } else { + // we must have at least one `attr` annotation + unreachable!( + "`build_abstract` encountered a node without any annotations." + ) + } } - ir::StaticControl::Par(_spar) => { - todo!() + ir::StaticControl::Par(spar) => { + if is_acyclic(spar) && is_inline(spar) { + // @NUM_STATES(n) @ACYCLIC @INLINE + todo!() + } else if is_offload(spar) { + // @NUM_STATES(1) @OFFLOAD + todo!() + } else { + // we must have at least one `attr` annotation + unreachable!( + "`build_abstract` encountered a node without any annotations." + ) + } } ir::StaticControl::Invoke(_) => { unreachable!( From 02c50cdf98acad7535d69371ed92ea91b10bcd8e Mon Sep 17 00:00:00 2001 From: Cynthia Shao Date: Sat, 13 Sep 2025 15:05:39 -0400 Subject: [PATCH 4/8] added comments and unreachable code for matching annotations --- calyx/opt/src/passes_experimental/fsm_builder.rs | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/calyx/opt/src/passes_experimental/fsm_builder.rs b/calyx/opt/src/passes_experimental/fsm_builder.rs index 312ac99224..d21980e22d 100644 --- a/calyx/opt/src/passes_experimental/fsm_builder.rs +++ b/calyx/opt/src/passes_experimental/fsm_builder.rs @@ -69,8 +69,10 @@ impl StaticSchedule<'_, '_> { match scon { ir::StaticControl::Empty(_) => (transitions_to_curr, None), ir::StaticControl::Enable(sen) => { - if is_acyclic(sen) { + if is_acyclic(sen) && is_inline(sen) { + // @NUM_STATES(n) @ACYCLIC @INLINE // The `@ACYCLIC` attribute requires that one state is allocated per cycle in a static enable. + // The `@INLINE` attribute requires that this node must allocate states for this enable. // For all parts of the FSM that want to transition to this enable, // register their transitions in self.state2trans. self.register_transitions( @@ -112,10 +114,12 @@ impl StaticSchedule<'_, '_> { )], looped_once_guard, ) - } else { + } else if is_inline(sen) { + // @NUM_STATES(n) @INLINE // In the absence of `@ACYCLIC`, the node must contain cycles, - // or have children that contain cycles; We'll run this placeholder code that - // creates one state for now. + // or have children that contain cycles + // We should create `n` states. + // We'll run this placeholder code that creates one state for now. self.register_transitions( self.state, &mut transitions_to_curr, @@ -133,6 +137,10 @@ impl StaticSchedule<'_, '_> { )], None, ) + } else { + unreachable!( + "`build_abstract` encountered a node without any annotations." + ) } } ir::StaticControl::Seq(sseq) => { From 85af358ec556849af70c47f42f585223b63f2964 Mon Sep 17 00:00:00 2001 From: Cynthia Shao Date: Sat, 8 Nov 2025 17:55:00 -0500 Subject: [PATCH 5/8] Implmented repeat offload and inlining. --- calyx/opt/src/default_passes.rs | 2 +- .../src/passes_experimental/fsm_builder.rs | 234 ++- .../med-fsm/static-seq-enable-inline.futil | 8 +- .../static-seq-repeat-inline-enable.expect | 73 + .../static-seq-repeat-inline-enable.futil | 37 + .../med-fsm/static-seq-repeat-inline.expect | 58 + .../med-fsm/static-seq-repeat-inline.futil | 34 + .../med-fsm/static-seq-repeat-offload.expect | 1862 +++++++++++++++++ .../med-fsm/static-seq-repeat-offload.futil | 321 +++ 9 files changed, 2609 insertions(+), 20 deletions(-) create mode 100644 tests/passes/med-fsm/static-seq-repeat-inline-enable.expect create mode 100644 tests/passes/med-fsm/static-seq-repeat-inline-enable.futil create mode 100644 tests/passes/med-fsm/static-seq-repeat-inline.expect create mode 100644 tests/passes/med-fsm/static-seq-repeat-inline.futil create mode 100644 tests/passes/med-fsm/static-seq-repeat-offload.expect create mode 100644 tests/passes/med-fsm/static-seq-repeat-offload.futil diff --git a/calyx/opt/src/default_passes.rs b/calyx/opt/src/default_passes.rs index 19d4ca0fef..0405cd2067 100644 --- a/calyx/opt/src/default_passes.rs +++ b/calyx/opt/src/default_passes.rs @@ -132,7 +132,7 @@ impl PassManager { GroupToInvoke, ComponentInliner, CombProp, - DeadCellRemoval, + // DeadCellRemoval, CellShare, SimplifyWithControl, CompileInvoke, diff --git a/calyx/opt/src/passes_experimental/fsm_builder.rs b/calyx/opt/src/passes_experimental/fsm_builder.rs index d21980e22d..c54543baf6 100644 --- a/calyx/opt/src/passes_experimental/fsm_builder.rs +++ b/calyx/opt/src/passes_experimental/fsm_builder.rs @@ -8,6 +8,8 @@ const UNROLL: ir::Attribute = ir::Attribute::Internal(ir::InternalAttr::UNROLL); const OFFLOAD: ir::Attribute = ir::Attribute::Internal(ir::InternalAttr::OFFLOAD); const INLINE: ir::Attribute = ir::Attribute::Internal(ir::InternalAttr::INLINE); +const NUM_STATES: ir::Attribute = + ir::Attribute::Internal(ir::InternalAttr::NUM_STATES); pub struct FSMBuilder {} @@ -51,6 +53,10 @@ fn is_inline(control: &T) -> bool { matches!(control.get_attributes().get(INLINE), Some(1)) } +fn get_num_states(control: &ir::StaticControl) -> u64 { + control.get_attribute(NUM_STATES).unwrap() +} + // A `StaticSchedule` is an abstract representation of fsms and maps out transitions, states, and assignments. // This implmentation includes functions to build up static schedules and transform them to `ir::RRC::FSM`s. impl StaticSchedule<'_, '_> { @@ -146,17 +152,20 @@ impl StaticSchedule<'_, '_> { ir::StaticControl::Seq(sseq) => { if is_acyclic(sseq) && is_inline(sseq) { // @NUM_STATES(n) @ACYCLIC @INLINE + ( - sseq.stmts.iter().fold( + sseq.stmts.iter().enumerate().fold( transitions_to_curr, - |transitions_to_this_stmt, stmt| { - self.build_abstract( - stmt, - guard.clone(), - transitions_to_this_stmt, - looped_once_guard.clone(), - ) - .0 + |transitions_to_this_stmt, (_, stmt)| { + let result = self + .build_abstract( + stmt, + guard.clone(), + transitions_to_this_stmt, + looped_once_guard.clone(), + ) + .0; + result }, ), None, @@ -181,7 +190,9 @@ impl StaticSchedule<'_, '_> { ) } else if is_offload(sseq) { // @NUM_STATES(1) @OFFLOAD - todo!() + unreachable!( + "`build_abstract` encountered an impossible offload of Static Seq node." + ) } else { // cyclic static seqs are not possible // we must have at least one `attr` annotation @@ -213,13 +224,149 @@ impl StaticSchedule<'_, '_> { // @NUM_STATES(1) @OFFLOAD // In the case of offload, we'll want to create a state with a register to count the number of // times to loop in place - todo!() + unreachable!( + "`build_abstract` offload of `static_repeat` nodes should have been transformed away." + ) } else if is_inline(srep) { // @NUM_STATES(n) @INLINE - // In the case of inline, we'll want to assign as many states as children of this loop, - // but create a register to count the amount of times looped, and assign - // backward edges from the end to the beginning. - todo!() + // Create a loop: the body has n states (from annotations) + // We build those states once, add a counter, and create a back edge + + // Register incoming transitions to start of repeat + self.register_transitions( + self.state, + &mut transitions_to_curr, + guard.clone(), + ); + + let loop_start_state = self.state; + + // Get the number of states the body needs from its annotation + let body_num_states = get_num_states(&srep.body); + + // Build the body ONCE to populate the state->assignments mapping + let (_body_exits, _) = self.build_abstract( + &srep.body, + guard.clone(), + vec![], + looped_once_guard.clone(), + ); + + // After building the body, self.state has advanced by body_num_states + // So the last state of the loop body is self.state - 1 + let loop_end_state = loop_start_state + body_num_states - 1; + + // Create a counter to track iterations + let counter_width = + calyx_utils::math::bits_needed_for(srep.num_repeats); + let counter = self.builder.add_primitive( + format!("repeat_counter_{}", loop_start_state), + "std_reg", + &[counter_width], + ); + counter + .borrow_mut() + .add_attribute(ir::BoolAttr::FSMControl, 1); + + let signal_on = self.builder.add_constant(1, 1); + let counter_max = self + .builder + .add_constant(srep.num_repeats - 1, counter_width); + + // Increment counter on the last state of the loop body + let incr = self.builder.add_primitive( + format!("repeat_incr_{}", loop_start_state), + "std_add", + &[counter_width], + ); + incr.borrow_mut() + .add_attribute(ir::BoolAttr::FSMControl, 1); + + let one = self.builder.add_constant(1, counter_width); + + // Assignments to increment the counter + let incr_assigns = vec![ + self.builder.build_assignment( + incr.borrow().get("left"), + counter.borrow().get("out"), + ir::Guard::True, + ), + self.builder.build_assignment( + incr.borrow().get("right"), + one.borrow().get("out"), + ir::Guard::True, + ), + self.builder.build_assignment( + counter.borrow().get("in"), + incr.borrow().get("out"), + ir::Guard::True, + ), + self.builder.build_assignment( + counter.borrow().get("write_en"), + signal_on.borrow().get("out"), + ir::Guard::True, + ), + ]; + + // Add increment assignments to the last state of the body + self.state2assigns + .entry(loop_end_state) + .and_modify(|assigns| { + assigns.extend(incr_assigns.clone()) + }) + .or_insert(incr_assigns); + + // Create guard: counter < num_repeats - 1 (loop condition) + let lt = self.builder.add_primitive( + format!("repeat_lt_{}", loop_start_state), + "std_lt", + &[counter_width], + ); + lt.borrow_mut().add_attribute(ir::BoolAttr::FSMControl, 1); + + let loop_cond_assigns = vec![ + self.builder.build_assignment( + lt.borrow().get("left"), + counter.borrow().get("out"), + ir::Guard::True, + ), + self.builder.build_assignment( + lt.borrow().get("right"), + counter_max.borrow().get("out"), + ir::Guard::True, + ), + ]; + + // These assignments should be continuous + self.builder.add_continuous_assignments(loop_cond_assigns); + + // Create the loop-back transition: if counter < max, go back to loop start + let loop_back_guard = + ir::Guard::port(lt.borrow().get("out")); + let loop_back_transition = IncompleteTransition::new( + loop_end_state, + loop_back_guard.clone(), + ); + + // Register the back edge + self.register_transitions( + loop_start_state, + &mut vec![loop_back_transition], + guard.clone(), + ); + + // Exit condition: counter >= max, exit the loop + let exit_guard = + ir::Guard::Not(Box::new(loop_back_guard.clone())); + + // Return transition from the final state when loop is done + ( + vec![IncompleteTransition::new( + loop_end_state, + exit_guard, + )], + None, + ) } else { // we must have at least one `attr` annotation unreachable!( @@ -407,6 +554,62 @@ impl StaticSchedule<'_, '_> { } impl Visitor for FSMBuilder { + fn finish_static_repeat( + &mut self, + s: &mut calyx_ir::StaticRepeat, + comp: &mut calyx_ir::Component, + sigs: &calyx_ir::LibrarySignatures, + _comps: &[calyx_ir::Component], + ) -> crate::traversal::VisResult { + if is_offload(s) { + let non_promoted_static_component = comp.is_static() + && !(comp + .attributes + .has(ir::Attribute::Bool(ir::BoolAttr::Promoted))); + + let mut builder = ir::Builder::new(comp, sigs); + let signal_on = builder.add_constant(1, 1); + let repeat_group = builder.add_static_group("repeat", s.latency); + let mut sch_generator = StaticSchedule::from(&mut builder); + + let trigger_fsm = { + // This FSM implements the schedule for the body of the repeat + let fsm = sch_generator.fsm_build( + &s.body, + Component { + non_promoted_static_component: Some( + non_promoted_static_component, + ), + static_control_component: true, + }, + ); + + let mut trigger_thread = builder.build_assignment( + fsm.borrow().get("start"), + signal_on.borrow().get("out"), + ir::Guard::True, + ); + // Make fsm[start] active for the entire execution of the repeat, + // not just the first cycle. This way, we can repeat the body the desired + // number of times. + trigger_thread + .guard + .add_interval(ir::StaticTiming::new((0, s.latency))); + trigger_thread + }; + + repeat_group.borrow_mut().assignments.push(trigger_fsm); + let mut enable = ir::StaticControl::Enable(ir::StaticEnable { + group: repeat_group, + attributes: ir::Attributes::default(), + }); + enable.get_mut_attributes().insert(INLINE, 1); + Ok(Action::static_change(enable)) + } else { + Ok(Action::Continue) + } + } + /// `finish_static_control` is called once, at the very end of traversing the control tree, /// when all child nodes have been traversed. We traverse the static control node from parent to /// child, and recurse inward to inline children. @@ -421,6 +624,7 @@ impl Visitor for FSMBuilder { && !(comp .attributes .has(ir::Attribute::Bool(ir::BoolAttr::Promoted))); + // Implementation for single static enable components and static seqs for now. let mut builder = ir::Builder::new(comp, sigs); diff --git a/tests/passes/med-fsm/static-seq-enable-inline.futil b/tests/passes/med-fsm/static-seq-enable-inline.futil index 19dff24cea..4dd589a3f8 100644 --- a/tests/passes/med-fsm/static-seq-enable-inline.futil +++ b/tests/passes/med-fsm/static-seq-enable-inline.futil @@ -22,10 +22,10 @@ component main() -> () { static seq { A; static seq { - A; - B; - A; - B; + A; + B; + A; + B; } A; } diff --git a/tests/passes/med-fsm/static-seq-repeat-inline-enable.expect b/tests/passes/med-fsm/static-seq-repeat-inline-enable.expect new file mode 100644 index 0000000000..c52c2e8fb0 --- /dev/null +++ b/tests/passes/med-fsm/static-seq-repeat-inline-enable.expect @@ -0,0 +1,73 @@ +import "primitives/core.futil"; +import "primitives/memories/comb.futil"; +component main(@go go: 1, @clk clk: 1, @reset reset: 1) -> (@done done: 1) { + cells { + @data a = std_reg(2); + @data b = std_reg(2); + @data c = std_reg(2); + @generated @fsm_control repeat_counter_0 = std_reg(20); + @generated @fsm_control repeat_incr_0 = std_add(20); + @generated @fsm_control repeat_lt_0 = std_lt(20); + @generated fsm_0 = std_wire(1); + @generated fsm_1 = std_wire(1); + @generated fsm_2 = std_wire(1); + @generated fsm_3 = std_wire(1); + @generated fsm_4 = std_wire(1); + @generated fsm_5 = std_wire(1); + @generated fsm_6 = std_wire(1); + @generated fsm_7 = std_wire(1); + @generated @fsm_control looped_once = std_reg(1); + } + wires { + fsm fsm { + 0 : { + fsm_0.in = fsm[start] ? 1'd1; + looped_once.in = fsm[start] ? 1'd1; + looped_once.write_en = 1'd1; + fsm[done] = looped_once.out; + } => { + fsm[start] -> 1, + default -> 0, + }, + 1 : { + fsm_1.in = 1'd1; + } => 2, + 2 : { + fsm_2.in = 1'd1; + } => 3, + 3 : { + fsm_3.in = 1'd1; + } => 4, + 4 : { + fsm_4.in = 1'd1; + } => 5, + 5 : { + fsm_5.in = 1'd1; + } => { + repeat_lt_0.out -> 0, + !repeat_lt_0.out -> 6, + default -> 5, + }, + 6 : { + fsm_6.in = 1'd1; + } => 7, + 7 : { + fsm_7.in = 1'd1; + } => 0, + } + b.write_en = fsm_0.out | fsm_1.out | fsm_3.out | fsm_4.out | fsm_6.out ? 1'd1; + b.in = fsm_1.out | fsm_2.out | fsm_4.out | fsm_5.out | fsm_6.out | fsm_7.out ? 2'd1; + b.in = fsm_0.out | fsm_3.out ? 2'd0; + repeat_incr_0.left = fsm_5.out ? repeat_counter_0.out; + repeat_incr_0.right = fsm_5.out ? 20'd1; + repeat_counter_0.write_en = fsm_5.out ? 1'd1; + repeat_counter_0.in = fsm_5.out ? repeat_incr_0.out; + c.write_en = fsm_2.out | fsm_5.out | fsm_7.out ? 1'd1; + c.in = fsm_1.out | fsm_2.out | fsm_4.out | fsm_5.out | fsm_6.out | fsm_7.out ? 2'd3; + repeat_lt_0.left = repeat_counter_0.out; + repeat_lt_0.right = 20'd999999; + } + control { + fsm; + } +} diff --git a/tests/passes/med-fsm/static-seq-repeat-inline-enable.futil b/tests/passes/med-fsm/static-seq-repeat-inline-enable.futil new file mode 100644 index 0000000000..511a536b1b --- /dev/null +++ b/tests/passes/med-fsm/static-seq-repeat-inline-enable.futil @@ -0,0 +1,37 @@ +// -p med-fsm +import "primitives/core.futil"; +import "primitives/memories/comb.futil"; + +component main() -> () { + cells { + a = std_reg(2); + b = std_reg(2); + c = std_reg(2); + } + wires { + static<1> group A { + a.in = 2'd0; + a.write_en = %0 ? 1'd1; + } + static<2> group B { + b.in = 2'd1; + b.write_en = %0 ? 1'd1; + c.in = 2'd3; + c.write_en = %1 ? 1'd1; + } + } + + control { + static seq { + static repeat 1000000 { + static seq { + A; // 0 + B; // 1 2 + A; // 3 + B; // 4 5 + } + } + B; // 6 7 + } + } +} \ No newline at end of file diff --git a/tests/passes/med-fsm/static-seq-repeat-inline.expect b/tests/passes/med-fsm/static-seq-repeat-inline.expect new file mode 100644 index 0000000000..2a98591573 --- /dev/null +++ b/tests/passes/med-fsm/static-seq-repeat-inline.expect @@ -0,0 +1,58 @@ +import "primitives/core.futil"; +import "primitives/memories/comb.futil"; +component main(@go go: 1, @clk clk: 1, @reset reset: 1) -> (@done done: 1) { + cells { + @data a = std_reg(2); + @data b = std_reg(2); + @generated @fsm_control repeat_counter_0 = std_reg(20); + @generated @fsm_control repeat_incr_0 = std_add(20); + @generated @fsm_control repeat_lt_0 = std_lt(20); + @generated fsm_0 = std_wire(1); + @generated fsm_1 = std_wire(1); + @generated fsm_2 = std_wire(1); + @generated fsm_3 = std_wire(1); + @generated fsm_4 = std_wire(1); + @generated @fsm_control looped_once = std_reg(1); + } + wires { + fsm fsm { + 0 : { + fsm_0.in = fsm[start] ? 1'd1; + looped_once.in = fsm[start] ? 1'd1; + looped_once.write_en = 1'd1; + fsm[done] = looped_once.out; + } => { + fsm[start] -> 1, + default -> 0, + }, + 1 : { + fsm_1.in = 1'd1; + } => 2, + 2 : { + fsm_2.in = 1'd1; + } => 3, + 3 : { + fsm_3.in = 1'd1; + } => { + repeat_lt_0.out -> 0, + !repeat_lt_0.out -> 4, + default -> 3, + }, + 4 : { + fsm_4.in = 1'd1; + } => 0, + } + repeat_incr_0.left = fsm_3.out ? repeat_counter_0.out; + repeat_incr_0.right = fsm_3.out ? 20'd1; + a.write_en = fsm_0.out | fsm_1.out | fsm_2.out | fsm_3.out | fsm_4.out ? 1'd1; + a.in = fsm_1.out | fsm_3.out | fsm_4.out ? 2'd1; + a.in = fsm_0.out | fsm_2.out ? 2'd0; + repeat_counter_0.write_en = fsm_3.out ? 1'd1; + repeat_counter_0.in = fsm_3.out ? repeat_incr_0.out; + repeat_lt_0.left = repeat_counter_0.out; + repeat_lt_0.right = 20'd999999; + } + control { + fsm; + } +} diff --git a/tests/passes/med-fsm/static-seq-repeat-inline.futil b/tests/passes/med-fsm/static-seq-repeat-inline.futil new file mode 100644 index 0000000000..a10f1a88d4 --- /dev/null +++ b/tests/passes/med-fsm/static-seq-repeat-inline.futil @@ -0,0 +1,34 @@ +// -p med-fsm +import "primitives/core.futil"; +import "primitives/memories/comb.futil"; + +component main() -> () { + cells { + a = std_reg(2); + b = std_reg(2); + } + wires { + static<1> group A { + a.in = 2'd0; + a.write_en = %0 ? 1'd1; + } + static<1> group B { + b.in = 2'd1; + b.write_en = %0 ? 1'd1; + } + } + + control { + static seq { + static repeat 1000000 { + static seq { + A; + B; + A; + B; + } + } + B; + } + } +} \ No newline at end of file diff --git a/tests/passes/med-fsm/static-seq-repeat-offload.expect b/tests/passes/med-fsm/static-seq-repeat-offload.expect new file mode 100644 index 0000000000..a7b15d4f84 --- /dev/null +++ b/tests/passes/med-fsm/static-seq-repeat-offload.expect @@ -0,0 +1,1862 @@ +import "primitives/core.futil"; +import "primitives/memories/comb.futil"; +import "primitives/binary_operators.futil"; +component main(@go go: 1, @clk clk: 1, @reset reset: 1) -> (@done done: 1) { + cells { + @data a = std_reg(2); + @data mult = std_mult_pipe(2); + @data b = std_reg(2); + @data c = std_reg(2); + @data d = std_reg(2); + @data r1 = std_reg(1); + @generated fsm_0 = std_wire(1); + @generated fsm_1 = std_wire(1); + @generated fsm_2 = std_wire(1); + @generated fsm_3 = std_wire(1); + @generated fsm_4 = std_wire(1); + @generated fsm_5 = std_wire(1); + @generated fsm_6 = std_wire(1); + @generated fsm_7 = std_wire(1); + @generated fsm_8 = std_wire(1); + @generated fsm_9 = std_wire(1); + @generated fsm_10 = std_wire(1); + @generated fsm_11 = std_wire(1); + @generated fsm_12 = std_wire(1); + @generated fsm_13 = std_wire(1); + @generated fsm_14 = std_wire(1); + @generated fsm_15 = std_wire(1); + @generated fsm_16 = std_wire(1); + @generated fsm_17 = std_wire(1); + @generated fsm_18 = std_wire(1); + @generated fsm_19 = std_wire(1); + @generated fsm_20 = std_wire(1); + @generated fsm_21 = std_wire(1); + @generated fsm_22 = std_wire(1); + @generated fsm_23 = std_wire(1); + @generated fsm_24 = std_wire(1); + @generated fsm_25 = std_wire(1); + @generated fsm_26 = std_wire(1); + @generated fsm_27 = std_wire(1); + @generated fsm_28 = std_wire(1); + @generated fsm_29 = std_wire(1); + @generated fsm_30 = std_wire(1); + @generated fsm_31 = std_wire(1); + @generated fsm_32 = std_wire(1); + @generated fsm_33 = std_wire(1); + @generated fsm_34 = std_wire(1); + @generated fsm_35 = std_wire(1); + @generated fsm_36 = std_wire(1); + @generated fsm_37 = std_wire(1); + @generated fsm_38 = std_wire(1); + @generated fsm_39 = std_wire(1); + @generated fsm_40 = std_wire(1); + @generated fsm_41 = std_wire(1); + @generated fsm_42 = std_wire(1); + @generated fsm_43 = std_wire(1); + @generated fsm_44 = std_wire(1); + @generated fsm_45 = std_wire(1); + @generated fsm_46 = std_wire(1); + @generated fsm_47 = std_wire(1); + @generated fsm_48 = std_wire(1); + @generated fsm_49 = std_wire(1); + @generated fsm_50 = std_wire(1); + @generated fsm_51 = std_wire(1); + @generated fsm_52 = std_wire(1); + @generated fsm_53 = std_wire(1); + @generated fsm_54 = std_wire(1); + @generated fsm_55 = std_wire(1); + @generated fsm_56 = std_wire(1); + @generated fsm_57 = std_wire(1); + @generated fsm_58 = std_wire(1); + @generated fsm_59 = std_wire(1); + @generated fsm_60 = std_wire(1); + @generated fsm_61 = std_wire(1); + @generated fsm_62 = std_wire(1); + @generated fsm_63 = std_wire(1); + @generated fsm_64 = std_wire(1); + @generated fsm_65 = std_wire(1); + @generated fsm_66 = std_wire(1); + @generated fsm_67 = std_wire(1); + @generated fsm_68 = std_wire(1); + @generated fsm_69 = std_wire(1); + @generated fsm_70 = std_wire(1); + @generated fsm_71 = std_wire(1); + @generated fsm_72 = std_wire(1); + @generated fsm_73 = std_wire(1); + @generated fsm_74 = std_wire(1); + @generated fsm_75 = std_wire(1); + @generated fsm_76 = std_wire(1); + @generated fsm_77 = std_wire(1); + @generated fsm_78 = std_wire(1); + @generated fsm_79 = std_wire(1); + @generated fsm_80 = std_wire(1); + @generated fsm_81 = std_wire(1); + @generated fsm_82 = std_wire(1); + @generated fsm_83 = std_wire(1); + @generated fsm_84 = std_wire(1); + @generated fsm_85 = std_wire(1); + @generated fsm_86 = std_wire(1); + @generated fsm_87 = std_wire(1); + @generated fsm_88 = std_wire(1); + @generated fsm_89 = std_wire(1); + @generated fsm_90 = std_wire(1); + @generated fsm_91 = std_wire(1); + @generated fsm_92 = std_wire(1); + @generated fsm_93 = std_wire(1); + @generated fsm_94 = std_wire(1); + @generated fsm_95 = std_wire(1); + @generated fsm_96 = std_wire(1); + @generated fsm_97 = std_wire(1); + @generated fsm_98 = std_wire(1); + @generated fsm_99 = std_wire(1); + @generated fsm_100 = std_wire(1); + @generated fsm_101 = std_wire(1); + @generated fsm_102 = std_wire(1); + @generated fsm_103 = std_wire(1); + @generated fsm_104 = std_wire(1); + @generated fsm_105 = std_wire(1); + @generated fsm_106 = std_wire(1); + @generated fsm_107 = std_wire(1); + @generated fsm_108 = std_wire(1); + @generated fsm_109 = std_wire(1); + @generated fsm_110 = std_wire(1); + @generated fsm_111 = std_wire(1); + @generated fsm_112 = std_wire(1); + @generated fsm_113 = std_wire(1); + @generated fsm_114 = std_wire(1); + @generated fsm_115 = std_wire(1); + @generated fsm_116 = std_wire(1); + @generated fsm_117 = std_wire(1); + @generated fsm_118 = std_wire(1); + @generated fsm_119 = std_wire(1); + @generated fsm_120 = std_wire(1); + @generated fsm_121 = std_wire(1); + @generated fsm_122 = std_wire(1); + @generated fsm_123 = std_wire(1); + @generated fsm_124 = std_wire(1); + @generated fsm_125 = std_wire(1); + @generated fsm_126 = std_wire(1); + @generated fsm_127 = std_wire(1); + @generated fsm_128 = std_wire(1); + @generated fsm_129 = std_wire(1); + @generated fsm_130 = std_wire(1); + @generated fsm_131 = std_wire(1); + @generated fsm_132 = std_wire(1); + @generated fsm_133 = std_wire(1); + @generated fsm_134 = std_wire(1); + @generated fsm_135 = std_wire(1); + @generated fsm_136 = std_wire(1); + @generated fsm_137 = std_wire(1); + @generated fsm_138 = std_wire(1); + @generated fsm_139 = std_wire(1); + @generated fsm_140 = std_wire(1); + @generated fsm_141 = std_wire(1); + @generated fsm_142 = std_wire(1); + @generated fsm_143 = std_wire(1); + @generated fsm_144 = std_wire(1); + @generated fsm_145 = std_wire(1); + @generated fsm_146 = std_wire(1); + @generated fsm_147 = std_wire(1); + @generated fsm_148 = std_wire(1); + @generated fsm_149 = std_wire(1); + @generated fsm_150 = std_wire(1); + @generated fsm_151 = std_wire(1); + @generated fsm_152 = std_wire(1); + @generated fsm_153 = std_wire(1); + @generated fsm_154 = std_wire(1); + @generated fsm_155 = std_wire(1); + @generated fsm_156 = std_wire(1); + @generated fsm_157 = std_wire(1); + @generated fsm_158 = std_wire(1); + @generated fsm_159 = std_wire(1); + @generated fsm_160 = std_wire(1); + @generated fsm_161 = std_wire(1); + @generated fsm_162 = std_wire(1); + @generated fsm_163 = std_wire(1); + @generated fsm_164 = std_wire(1); + @generated fsm_165 = std_wire(1); + @generated fsm_166 = std_wire(1); + @generated fsm_167 = std_wire(1); + @generated fsm_168 = std_wire(1); + @generated fsm_169 = std_wire(1); + @generated fsm_170 = std_wire(1); + @generated fsm_171 = std_wire(1); + @generated fsm_172 = std_wire(1); + @generated fsm_173 = std_wire(1); + @generated fsm_174 = std_wire(1); + @generated fsm_175 = std_wire(1); + @generated fsm_176 = std_wire(1); + @generated fsm_177 = std_wire(1); + @generated fsm_178 = std_wire(1); + @generated fsm_179 = std_wire(1); + @generated fsm_180 = std_wire(1); + @generated fsm_181 = std_wire(1); + @generated fsm_182 = std_wire(1); + @generated fsm_183 = std_wire(1); + @generated fsm_184 = std_wire(1); + @generated fsm_185 = std_wire(1); + @generated fsm_186 = std_wire(1); + @generated fsm_187 = std_wire(1); + @generated fsm_188 = std_wire(1); + @generated fsm_189 = std_wire(1); + @generated fsm_190 = std_wire(1); + @generated fsm_191 = std_wire(1); + @generated fsm_192 = std_wire(1); + @generated fsm_193 = std_wire(1); + @generated fsm_194 = std_wire(1); + @generated fsm_195 = std_wire(1); + @generated fsm_196 = std_wire(1); + @generated fsm_197 = std_wire(1); + @generated fsm_198 = std_wire(1); + @generated fsm_199 = std_wire(1); + @generated fsm_200 = std_wire(1); + @generated fsm_201 = std_wire(1); + @generated fsm_202 = std_wire(1); + @generated fsm_203 = std_wire(1); + @generated fsm_204 = std_wire(1); + @generated fsm_205 = std_wire(1); + @generated fsm_206 = std_wire(1); + @generated fsm_207 = std_wire(1); + @generated fsm_208 = std_wire(1); + @generated fsm_209 = std_wire(1); + @generated fsm_210 = std_wire(1); + @generated fsm_211 = std_wire(1); + @generated fsm_212 = std_wire(1); + @generated fsm_213 = std_wire(1); + @generated fsm_214 = std_wire(1); + @generated fsm_215 = std_wire(1); + @generated fsm_216 = std_wire(1); + @generated fsm_217 = std_wire(1); + @generated fsm_218 = std_wire(1); + @generated fsm_219 = std_wire(1); + @generated fsm_220 = std_wire(1); + @generated fsm_221 = std_wire(1); + @generated fsm_222 = std_wire(1); + @generated fsm_223 = std_wire(1); + @generated fsm_224 = std_wire(1); + @generated fsm_225 = std_wire(1); + @generated fsm_226 = std_wire(1); + @generated fsm_227 = std_wire(1); + @generated fsm_228 = std_wire(1); + @generated fsm_229 = std_wire(1); + @generated fsm_230 = std_wire(1); + @generated fsm_231 = std_wire(1); + @generated fsm_232 = std_wire(1); + @generated fsm_233 = std_wire(1); + @generated fsm_234 = std_wire(1); + @generated fsm_235 = std_wire(1); + @generated fsm_236 = std_wire(1); + @generated fsm_237 = std_wire(1); + @generated fsm_238 = std_wire(1); + @generated fsm_239 = std_wire(1); + @generated fsm_240 = std_wire(1); + @generated fsm_241 = std_wire(1); + @generated fsm_242 = std_wire(1); + @generated fsm_243 = std_wire(1); + @generated fsm_244 = std_wire(1); + @generated fsm_245 = std_wire(1); + @generated fsm_246 = std_wire(1); + @generated fsm_247 = std_wire(1); + @generated fsm_248 = std_wire(1); + @generated fsm_249 = std_wire(1); + @generated fsm_250 = std_wire(1); + @generated fsm_251 = std_wire(1); + @generated fsm_252 = std_wire(1); + @generated fsm_253 = std_wire(1); + @generated fsm_254 = std_wire(1); + @generated fsm_255 = std_wire(1); + @generated fsm_256 = std_wire(1); + @generated fsm_257 = std_wire(1); + @generated fsm_258 = std_wire(1); + @generated fsm_259 = std_wire(1); + @generated fsm_260 = std_wire(1); + @generated fsm_261 = std_wire(1); + @generated fsm_262 = std_wire(1); + @generated fsm_263 = std_wire(1); + @generated fsm_264 = std_wire(1); + @generated fsm_265 = std_wire(1); + @generated fsm_266 = std_wire(1); + @generated fsm_267 = std_wire(1); + @generated fsm_268 = std_wire(1); + @generated fsm_269 = std_wire(1); + @generated fsm_270 = std_wire(1); + @generated fsm_271 = std_wire(1); + @generated fsm_272 = std_wire(1); + @generated fsm_273 = std_wire(1); + @generated fsm_274 = std_wire(1); + @generated fsm_275 = std_wire(1); + @generated fsm_276 = std_wire(1); + @generated fsm_277 = std_wire(1); + @generated fsm_278 = std_wire(1); + @generated fsm_279 = std_wire(1); + @generated fsm_280 = std_wire(1); + @generated fsm_281 = std_wire(1); + @generated fsm_282 = std_wire(1); + @generated fsm_283 = std_wire(1); + @generated fsm_284 = std_wire(1); + @generated fsm_285 = std_wire(1); + @generated fsm_286 = std_wire(1); + @generated fsm_287 = std_wire(1); + @generated fsm_288 = std_wire(1); + @generated fsm_289 = std_wire(1); + @generated fsm_290 = std_wire(1); + @generated fsm_291 = std_wire(1); + @generated fsm_292 = std_wire(1); + @generated fsm_293 = std_wire(1); + @generated fsm_294 = std_wire(1); + @generated fsm_295 = std_wire(1); + @generated fsm_296 = std_wire(1); + @generated fsm_297 = std_wire(1); + @generated fsm_298 = std_wire(1); + @generated fsm_299 = std_wire(1); + @generated fsm_300 = std_wire(1); + @generated fsm_301 = std_wire(1); + @generated fsm_302 = std_wire(1); + @generated fsm_303 = std_wire(1); + @generated fsm_304 = std_wire(1); + @generated fsm_305 = std_wire(1); + @generated fsm_306 = std_wire(1); + @generated fsm_307 = std_wire(1); + @generated fsm_308 = std_wire(1); + @generated fsm_309 = std_wire(1); + @generated fsm_310 = std_wire(1); + @generated fsm_311 = std_wire(1); + @generated fsm_312 = std_wire(1); + @generated fsm_313 = std_wire(1); + @generated fsm_314 = std_wire(1); + @generated fsm_315 = std_wire(1); + @generated fsm_316 = std_wire(1); + @generated fsm_317 = std_wire(1); + @generated fsm_318 = std_wire(1); + @generated fsm_319 = std_wire(1); + @generated fsm_320 = std_wire(1); + @generated fsm_321 = std_wire(1); + @generated fsm_322 = std_wire(1); + @generated fsm_323 = std_wire(1); + @generated fsm_324 = std_wire(1); + @generated fsm_325 = std_wire(1); + @generated fsm_326 = std_wire(1); + @generated fsm_327 = std_wire(1); + @generated fsm_328 = std_wire(1); + @generated fsm_329 = std_wire(1); + @generated fsm_330 = std_wire(1); + @generated fsm_331 = std_wire(1); + @generated fsm_332 = std_wire(1); + @generated fsm_333 = std_wire(1); + @generated fsm_334 = std_wire(1); + @generated fsm_335 = std_wire(1); + @generated fsm_336 = std_wire(1); + @generated fsm_337 = std_wire(1); + @generated fsm_338 = std_wire(1); + @generated fsm_339 = std_wire(1); + @generated fsm_340 = std_wire(1); + @generated fsm_341 = std_wire(1); + @generated fsm_342 = std_wire(1); + @generated fsm_343 = std_wire(1); + @generated fsm_344 = std_wire(1); + @generated fsm_345 = std_wire(1); + @generated fsm_346 = std_wire(1); + @generated fsm_347 = std_wire(1); + @generated fsm_348 = std_wire(1); + @generated fsm_349 = std_wire(1); + @generated fsm_350 = std_wire(1); + @generated fsm_351 = std_wire(1); + @generated fsm_352 = std_wire(1); + @generated fsm_353 = std_wire(1); + @generated fsm_354 = std_wire(1); + @generated fsm_355 = std_wire(1); + @generated fsm_356 = std_wire(1); + @generated fsm_357 = std_wire(1); + @generated fsm_358 = std_wire(1); + @generated fsm_359 = std_wire(1); + @generated fsm_360 = std_wire(1); + @generated fsm_361 = std_wire(1); + @generated fsm_362 = std_wire(1); + @generated fsm_363 = std_wire(1); + @generated fsm_364 = std_wire(1); + @generated fsm_365 = std_wire(1); + @generated fsm_366 = std_wire(1); + @generated fsm_367 = std_wire(1); + @generated fsm_368 = std_wire(1); + @generated fsm_369 = std_wire(1); + @generated fsm_370 = std_wire(1); + @generated fsm_371 = std_wire(1); + @generated fsm_372 = std_wire(1); + @generated fsm_373 = std_wire(1); + @generated fsm_374 = std_wire(1); + @generated fsm_375 = std_wire(1); + @generated fsm_376 = std_wire(1); + @generated fsm_377 = std_wire(1); + @generated fsm_378 = std_wire(1); + @generated fsm_379 = std_wire(1); + @generated fsm_380 = std_wire(1); + @generated fsm_381 = std_wire(1); + @generated fsm_382 = std_wire(1); + @generated fsm_383 = std_wire(1); + @generated fsm_384 = std_wire(1); + @generated fsm_385 = std_wire(1); + @generated fsm_386 = std_wire(1); + @generated fsm_387 = std_wire(1); + @generated fsm_388 = std_wire(1); + @generated fsm_389 = std_wire(1); + @generated fsm_390 = std_wire(1); + @generated fsm_391 = std_wire(1); + @generated fsm_392 = std_wire(1); + @generated fsm_393 = std_wire(1); + @generated fsm_394 = std_wire(1); + @generated fsm_395 = std_wire(1); + @generated fsm_396 = std_wire(1); + @generated fsm_397 = std_wire(1); + @generated fsm_398 = std_wire(1); + @generated fsm_399 = std_wire(1); + @generated fsm_400 = std_wire(1); + @generated fsm_401 = std_wire(1); + @generated fsm_402 = std_wire(1); + @generated fsm_403 = std_wire(1); + @generated fsm_404 = std_wire(1); + @generated fsm_405 = std_wire(1); + @generated fsm_406 = std_wire(1); + @generated fsm_407 = std_wire(1); + @generated fsm_408 = std_wire(1); + @generated fsm_409 = std_wire(1); + @generated fsm_410 = std_wire(1); + @generated fsm_411 = std_wire(1); + @generated fsm_412 = std_wire(1); + @generated fsm_413 = std_wire(1); + @generated fsm_414 = std_wire(1); + @generated fsm_415 = std_wire(1); + @generated fsm_416 = std_wire(1); + @generated fsm_417 = std_wire(1); + @generated fsm_418 = std_wire(1); + @generated fsm_419 = std_wire(1); + @generated fsm_420 = std_wire(1); + @generated fsm_421 = std_wire(1); + @generated fsm_422 = std_wire(1); + @generated fsm_423 = std_wire(1); + @generated fsm_424 = std_wire(1); + @generated fsm_425 = std_wire(1); + @generated fsm_426 = std_wire(1); + @generated fsm_427 = std_wire(1); + @generated fsm_428 = std_wire(1); + @generated fsm_429 = std_wire(1); + @generated fsm_430 = std_wire(1); + @generated fsm_431 = std_wire(1); + @generated fsm_432 = std_wire(1); + @generated fsm_433 = std_wire(1); + @generated fsm_434 = std_wire(1); + @generated fsm_435 = std_wire(1); + @generated fsm_436 = std_wire(1); + @generated fsm_437 = std_wire(1); + @generated fsm_438 = std_wire(1); + @generated fsm_439 = std_wire(1); + @generated fsm_440 = std_wire(1); + @generated fsm_441 = std_wire(1); + @generated fsm_442 = std_wire(1); + @generated fsm_443 = std_wire(1); + @generated fsm_444 = std_wire(1); + @generated fsm_445 = std_wire(1); + @generated fsm_446 = std_wire(1); + @generated fsm_447 = std_wire(1); + @generated fsm_448 = std_wire(1); + @generated fsm_449 = std_wire(1); + @generated @fsm_control looped_once = std_reg(1); + @generated group_counter = std_reg(29); + @generated const449999999_29_ = std_wire(29); + @generated adder = std_add(29); + @generated fsm0_0 = std_wire(1); + @generated fsm0_1 = std_wire(1); + @generated @fsm_control looped_once0 = std_reg(1); + } + wires { + fsm fsm { + 0 : { + fsm_0.in = fsm[start] ? 1'd1; + looped_once.in = fsm[start] ? 1'd1; + looped_once.write_en = 1'd1; + fsm[done] = looped_once.out; + } => { + fsm[start] -> 1, + default -> 0, + }, + 1 : { + fsm_1.in = 1'd1; + } => 2, + 2 : { + fsm_2.in = 1'd1; + } => 3, + 3 : { + fsm_3.in = 1'd1; + } => 4, + 4 : { + fsm_4.in = 1'd1; + } => 5, + 5 : { + fsm_5.in = 1'd1; + } => 6, + 6 : { + fsm_6.in = 1'd1; + } => 7, + 7 : { + fsm_7.in = 1'd1; + } => 8, + 8 : { + fsm_8.in = 1'd1; + } => 9, + 9 : { + fsm_9.in = 1'd1; + } => 10, + 10 : { + fsm_10.in = 1'd1; + } => 11, + 11 : { + fsm_11.in = 1'd1; + } => 12, + 12 : { + fsm_12.in = 1'd1; + } => 13, + 13 : { + fsm_13.in = 1'd1; + } => 14, + 14 : { + fsm_14.in = 1'd1; + } => 15, + 15 : { + fsm_15.in = 1'd1; + } => 16, + 16 : { + fsm_16.in = 1'd1; + } => 17, + 17 : { + fsm_17.in = 1'd1; + } => 18, + 18 : { + fsm_18.in = 1'd1; + } => 19, + 19 : { + fsm_19.in = 1'd1; + } => 20, + 20 : { + fsm_20.in = 1'd1; + } => 21, + 21 : { + fsm_21.in = 1'd1; + } => 22, + 22 : { + fsm_22.in = 1'd1; + } => 23, + 23 : { + fsm_23.in = 1'd1; + } => 24, + 24 : { + fsm_24.in = 1'd1; + } => 25, + 25 : { + fsm_25.in = 1'd1; + } => 26, + 26 : { + fsm_26.in = 1'd1; + } => 27, + 27 : { + fsm_27.in = 1'd1; + } => 28, + 28 : { + fsm_28.in = 1'd1; + } => 29, + 29 : { + fsm_29.in = 1'd1; + } => 30, + 30 : { + fsm_30.in = 1'd1; + } => 31, + 31 : { + fsm_31.in = 1'd1; + } => 32, + 32 : { + fsm_32.in = 1'd1; + } => 33, + 33 : { + fsm_33.in = 1'd1; + } => 34, + 34 : { + fsm_34.in = 1'd1; + } => 35, + 35 : { + fsm_35.in = 1'd1; + } => 36, + 36 : { + fsm_36.in = 1'd1; + } => 37, + 37 : { + fsm_37.in = 1'd1; + } => 38, + 38 : { + fsm_38.in = 1'd1; + } => 39, + 39 : { + fsm_39.in = 1'd1; + } => 40, + 40 : { + fsm_40.in = 1'd1; + } => 41, + 41 : { + fsm_41.in = 1'd1; + } => 42, + 42 : { + fsm_42.in = 1'd1; + } => 43, + 43 : { + fsm_43.in = 1'd1; + } => 44, + 44 : { + fsm_44.in = 1'd1; + } => 45, + 45 : { + fsm_45.in = 1'd1; + } => 46, + 46 : { + fsm_46.in = 1'd1; + } => 47, + 47 : { + fsm_47.in = 1'd1; + } => 48, + 48 : { + fsm_48.in = 1'd1; + } => 49, + 49 : { + fsm_49.in = 1'd1; + } => 50, + 50 : { + fsm_50.in = 1'd1; + } => 51, + 51 : { + fsm_51.in = 1'd1; + } => 52, + 52 : { + fsm_52.in = 1'd1; + } => 53, + 53 : { + fsm_53.in = 1'd1; + } => 54, + 54 : { + fsm_54.in = 1'd1; + } => 55, + 55 : { + fsm_55.in = 1'd1; + } => 56, + 56 : { + fsm_56.in = 1'd1; + } => 57, + 57 : { + fsm_57.in = 1'd1; + } => 58, + 58 : { + fsm_58.in = 1'd1; + } => 59, + 59 : { + fsm_59.in = 1'd1; + } => 60, + 60 : { + fsm_60.in = 1'd1; + } => 61, + 61 : { + fsm_61.in = 1'd1; + } => 62, + 62 : { + fsm_62.in = 1'd1; + } => 63, + 63 : { + fsm_63.in = 1'd1; + } => 64, + 64 : { + fsm_64.in = 1'd1; + } => 65, + 65 : { + fsm_65.in = 1'd1; + } => 66, + 66 : { + fsm_66.in = 1'd1; + } => 67, + 67 : { + fsm_67.in = 1'd1; + } => 68, + 68 : { + fsm_68.in = 1'd1; + } => 69, + 69 : { + fsm_69.in = 1'd1; + } => 70, + 70 : { + fsm_70.in = 1'd1; + } => 71, + 71 : { + fsm_71.in = 1'd1; + } => 72, + 72 : { + fsm_72.in = 1'd1; + } => 73, + 73 : { + fsm_73.in = 1'd1; + } => 74, + 74 : { + fsm_74.in = 1'd1; + } => 75, + 75 : { + fsm_75.in = 1'd1; + } => 76, + 76 : { + fsm_76.in = 1'd1; + } => 77, + 77 : { + fsm_77.in = 1'd1; + } => 78, + 78 : { + fsm_78.in = 1'd1; + } => 79, + 79 : { + fsm_79.in = 1'd1; + } => 80, + 80 : { + fsm_80.in = 1'd1; + } => 81, + 81 : { + fsm_81.in = 1'd1; + } => 82, + 82 : { + fsm_82.in = 1'd1; + } => 83, + 83 : { + fsm_83.in = 1'd1; + } => 84, + 84 : { + fsm_84.in = 1'd1; + } => 85, + 85 : { + fsm_85.in = 1'd1; + } => 86, + 86 : { + fsm_86.in = 1'd1; + } => 87, + 87 : { + fsm_87.in = 1'd1; + } => 88, + 88 : { + fsm_88.in = 1'd1; + } => 89, + 89 : { + fsm_89.in = 1'd1; + } => 90, + 90 : { + fsm_90.in = 1'd1; + } => 91, + 91 : { + fsm_91.in = 1'd1; + } => 92, + 92 : { + fsm_92.in = 1'd1; + } => 93, + 93 : { + fsm_93.in = 1'd1; + } => 94, + 94 : { + fsm_94.in = 1'd1; + } => 95, + 95 : { + fsm_95.in = 1'd1; + } => 96, + 96 : { + fsm_96.in = 1'd1; + } => 97, + 97 : { + fsm_97.in = 1'd1; + } => 98, + 98 : { + fsm_98.in = 1'd1; + } => 99, + 99 : { + fsm_99.in = 1'd1; + } => 100, + 100 : { + fsm_100.in = 1'd1; + } => 101, + 101 : { + fsm_101.in = 1'd1; + } => 102, + 102 : { + fsm_102.in = 1'd1; + } => 103, + 103 : { + fsm_103.in = 1'd1; + } => 104, + 104 : { + fsm_104.in = 1'd1; + } => 105, + 105 : { + fsm_105.in = 1'd1; + } => 106, + 106 : { + fsm_106.in = 1'd1; + } => 107, + 107 : { + fsm_107.in = 1'd1; + } => 108, + 108 : { + fsm_108.in = 1'd1; + } => 109, + 109 : { + fsm_109.in = 1'd1; + } => 110, + 110 : { + fsm_110.in = 1'd1; + } => 111, + 111 : { + fsm_111.in = 1'd1; + } => 112, + 112 : { + fsm_112.in = 1'd1; + } => 113, + 113 : { + fsm_113.in = 1'd1; + } => 114, + 114 : { + fsm_114.in = 1'd1; + } => 115, + 115 : { + fsm_115.in = 1'd1; + } => 116, + 116 : { + fsm_116.in = 1'd1; + } => 117, + 117 : { + fsm_117.in = 1'd1; + } => 118, + 118 : { + fsm_118.in = 1'd1; + } => 119, + 119 : { + fsm_119.in = 1'd1; + } => 120, + 120 : { + fsm_120.in = 1'd1; + } => 121, + 121 : { + fsm_121.in = 1'd1; + } => 122, + 122 : { + fsm_122.in = 1'd1; + } => 123, + 123 : { + fsm_123.in = 1'd1; + } => 124, + 124 : { + fsm_124.in = 1'd1; + } => 125, + 125 : { + fsm_125.in = 1'd1; + } => 126, + 126 : { + fsm_126.in = 1'd1; + } => 127, + 127 : { + fsm_127.in = 1'd1; + } => 128, + 128 : { + fsm_128.in = 1'd1; + } => 129, + 129 : { + fsm_129.in = 1'd1; + } => 130, + 130 : { + fsm_130.in = 1'd1; + } => 131, + 131 : { + fsm_131.in = 1'd1; + } => 132, + 132 : { + fsm_132.in = 1'd1; + } => 133, + 133 : { + fsm_133.in = 1'd1; + } => 134, + 134 : { + fsm_134.in = 1'd1; + } => 135, + 135 : { + fsm_135.in = 1'd1; + } => 136, + 136 : { + fsm_136.in = 1'd1; + } => 137, + 137 : { + fsm_137.in = 1'd1; + } => 138, + 138 : { + fsm_138.in = 1'd1; + } => 139, + 139 : { + fsm_139.in = 1'd1; + } => 140, + 140 : { + fsm_140.in = 1'd1; + } => 141, + 141 : { + fsm_141.in = 1'd1; + } => 142, + 142 : { + fsm_142.in = 1'd1; + } => 143, + 143 : { + fsm_143.in = 1'd1; + } => 144, + 144 : { + fsm_144.in = 1'd1; + } => 145, + 145 : { + fsm_145.in = 1'd1; + } => 146, + 146 : { + fsm_146.in = 1'd1; + } => 147, + 147 : { + fsm_147.in = 1'd1; + } => 148, + 148 : { + fsm_148.in = 1'd1; + } => 149, + 149 : { + fsm_149.in = 1'd1; + } => 150, + 150 : { + fsm_150.in = 1'd1; + } => 151, + 151 : { + fsm_151.in = 1'd1; + } => 152, + 152 : { + fsm_152.in = 1'd1; + } => 153, + 153 : { + fsm_153.in = 1'd1; + } => 154, + 154 : { + fsm_154.in = 1'd1; + } => 155, + 155 : { + fsm_155.in = 1'd1; + } => 156, + 156 : { + fsm_156.in = 1'd1; + } => 157, + 157 : { + fsm_157.in = 1'd1; + } => 158, + 158 : { + fsm_158.in = 1'd1; + } => 159, + 159 : { + fsm_159.in = 1'd1; + } => 160, + 160 : { + fsm_160.in = 1'd1; + } => 161, + 161 : { + fsm_161.in = 1'd1; + } => 162, + 162 : { + fsm_162.in = 1'd1; + } => 163, + 163 : { + fsm_163.in = 1'd1; + } => 164, + 164 : { + fsm_164.in = 1'd1; + } => 165, + 165 : { + fsm_165.in = 1'd1; + } => 166, + 166 : { + fsm_166.in = 1'd1; + } => 167, + 167 : { + fsm_167.in = 1'd1; + } => 168, + 168 : { + fsm_168.in = 1'd1; + } => 169, + 169 : { + fsm_169.in = 1'd1; + } => 170, + 170 : { + fsm_170.in = 1'd1; + } => 171, + 171 : { + fsm_171.in = 1'd1; + } => 172, + 172 : { + fsm_172.in = 1'd1; + } => 173, + 173 : { + fsm_173.in = 1'd1; + } => 174, + 174 : { + fsm_174.in = 1'd1; + } => 175, + 175 : { + fsm_175.in = 1'd1; + } => 176, + 176 : { + fsm_176.in = 1'd1; + } => 177, + 177 : { + fsm_177.in = 1'd1; + } => 178, + 178 : { + fsm_178.in = 1'd1; + } => 179, + 179 : { + fsm_179.in = 1'd1; + } => 180, + 180 : { + fsm_180.in = 1'd1; + } => 181, + 181 : { + fsm_181.in = 1'd1; + } => 182, + 182 : { + fsm_182.in = 1'd1; + } => 183, + 183 : { + fsm_183.in = 1'd1; + } => 184, + 184 : { + fsm_184.in = 1'd1; + } => 185, + 185 : { + fsm_185.in = 1'd1; + } => 186, + 186 : { + fsm_186.in = 1'd1; + } => 187, + 187 : { + fsm_187.in = 1'd1; + } => 188, + 188 : { + fsm_188.in = 1'd1; + } => 189, + 189 : { + fsm_189.in = 1'd1; + } => 190, + 190 : { + fsm_190.in = 1'd1; + } => 191, + 191 : { + fsm_191.in = 1'd1; + } => 192, + 192 : { + fsm_192.in = 1'd1; + } => 193, + 193 : { + fsm_193.in = 1'd1; + } => 194, + 194 : { + fsm_194.in = 1'd1; + } => 195, + 195 : { + fsm_195.in = 1'd1; + } => 196, + 196 : { + fsm_196.in = 1'd1; + } => 197, + 197 : { + fsm_197.in = 1'd1; + } => 198, + 198 : { + fsm_198.in = 1'd1; + } => 199, + 199 : { + fsm_199.in = 1'd1; + } => 200, + 200 : { + fsm_200.in = 1'd1; + } => 201, + 201 : { + fsm_201.in = 1'd1; + } => 202, + 202 : { + fsm_202.in = 1'd1; + } => 203, + 203 : { + fsm_203.in = 1'd1; + } => 204, + 204 : { + fsm_204.in = 1'd1; + } => 205, + 205 : { + fsm_205.in = 1'd1; + } => 206, + 206 : { + fsm_206.in = 1'd1; + } => 207, + 207 : { + fsm_207.in = 1'd1; + } => 208, + 208 : { + fsm_208.in = 1'd1; + } => 209, + 209 : { + fsm_209.in = 1'd1; + } => 210, + 210 : { + fsm_210.in = 1'd1; + } => 211, + 211 : { + fsm_211.in = 1'd1; + } => 212, + 212 : { + fsm_212.in = 1'd1; + } => 213, + 213 : { + fsm_213.in = 1'd1; + } => 214, + 214 : { + fsm_214.in = 1'd1; + } => 215, + 215 : { + fsm_215.in = 1'd1; + } => 216, + 216 : { + fsm_216.in = 1'd1; + } => 217, + 217 : { + fsm_217.in = 1'd1; + } => 218, + 218 : { + fsm_218.in = 1'd1; + } => 219, + 219 : { + fsm_219.in = 1'd1; + } => 220, + 220 : { + fsm_220.in = 1'd1; + } => 221, + 221 : { + fsm_221.in = 1'd1; + } => 222, + 222 : { + fsm_222.in = 1'd1; + } => 223, + 223 : { + fsm_223.in = 1'd1; + } => 224, + 224 : { + fsm_224.in = 1'd1; + } => 225, + 225 : { + fsm_225.in = 1'd1; + } => 226, + 226 : { + fsm_226.in = 1'd1; + } => 227, + 227 : { + fsm_227.in = 1'd1; + } => 228, + 228 : { + fsm_228.in = 1'd1; + } => 229, + 229 : { + fsm_229.in = 1'd1; + } => 230, + 230 : { + fsm_230.in = 1'd1; + } => 231, + 231 : { + fsm_231.in = 1'd1; + } => 232, + 232 : { + fsm_232.in = 1'd1; + } => 233, + 233 : { + fsm_233.in = 1'd1; + } => 234, + 234 : { + fsm_234.in = 1'd1; + } => 235, + 235 : { + fsm_235.in = 1'd1; + } => 236, + 236 : { + fsm_236.in = 1'd1; + } => 237, + 237 : { + fsm_237.in = 1'd1; + } => 238, + 238 : { + fsm_238.in = 1'd1; + } => 239, + 239 : { + fsm_239.in = 1'd1; + } => 240, + 240 : { + fsm_240.in = 1'd1; + } => 241, + 241 : { + fsm_241.in = 1'd1; + } => 242, + 242 : { + fsm_242.in = 1'd1; + } => 243, + 243 : { + fsm_243.in = 1'd1; + } => 244, + 244 : { + fsm_244.in = 1'd1; + } => 245, + 245 : { + fsm_245.in = 1'd1; + } => 246, + 246 : { + fsm_246.in = 1'd1; + } => 247, + 247 : { + fsm_247.in = 1'd1; + } => 248, + 248 : { + fsm_248.in = 1'd1; + } => 249, + 249 : { + fsm_249.in = 1'd1; + } => 250, + 250 : { + fsm_250.in = 1'd1; + } => 251, + 251 : { + fsm_251.in = 1'd1; + } => 252, + 252 : { + fsm_252.in = 1'd1; + } => 253, + 253 : { + fsm_253.in = 1'd1; + } => 254, + 254 : { + fsm_254.in = 1'd1; + } => 255, + 255 : { + fsm_255.in = 1'd1; + } => 256, + 256 : { + fsm_256.in = 1'd1; + } => 257, + 257 : { + fsm_257.in = 1'd1; + } => 258, + 258 : { + fsm_258.in = 1'd1; + } => 259, + 259 : { + fsm_259.in = 1'd1; + } => 260, + 260 : { + fsm_260.in = 1'd1; + } => 261, + 261 : { + fsm_261.in = 1'd1; + } => 262, + 262 : { + fsm_262.in = 1'd1; + } => 263, + 263 : { + fsm_263.in = 1'd1; + } => 264, + 264 : { + fsm_264.in = 1'd1; + } => 265, + 265 : { + fsm_265.in = 1'd1; + } => 266, + 266 : { + fsm_266.in = 1'd1; + } => 267, + 267 : { + fsm_267.in = 1'd1; + } => 268, + 268 : { + fsm_268.in = 1'd1; + } => 269, + 269 : { + fsm_269.in = 1'd1; + } => 270, + 270 : { + fsm_270.in = 1'd1; + } => 271, + 271 : { + fsm_271.in = 1'd1; + } => 272, + 272 : { + fsm_272.in = 1'd1; + } => 273, + 273 : { + fsm_273.in = 1'd1; + } => 274, + 274 : { + fsm_274.in = 1'd1; + } => 275, + 275 : { + fsm_275.in = 1'd1; + } => 276, + 276 : { + fsm_276.in = 1'd1; + } => 277, + 277 : { + fsm_277.in = 1'd1; + } => 278, + 278 : { + fsm_278.in = 1'd1; + } => 279, + 279 : { + fsm_279.in = 1'd1; + } => 280, + 280 : { + fsm_280.in = 1'd1; + } => 281, + 281 : { + fsm_281.in = 1'd1; + } => 282, + 282 : { + fsm_282.in = 1'd1; + } => 283, + 283 : { + fsm_283.in = 1'd1; + } => 284, + 284 : { + fsm_284.in = 1'd1; + } => 285, + 285 : { + fsm_285.in = 1'd1; + } => 286, + 286 : { + fsm_286.in = 1'd1; + } => 287, + 287 : { + fsm_287.in = 1'd1; + } => 288, + 288 : { + fsm_288.in = 1'd1; + } => 289, + 289 : { + fsm_289.in = 1'd1; + } => 290, + 290 : { + fsm_290.in = 1'd1; + } => 291, + 291 : { + fsm_291.in = 1'd1; + } => 292, + 292 : { + fsm_292.in = 1'd1; + } => 293, + 293 : { + fsm_293.in = 1'd1; + } => 294, + 294 : { + fsm_294.in = 1'd1; + } => 295, + 295 : { + fsm_295.in = 1'd1; + } => 296, + 296 : { + fsm_296.in = 1'd1; + } => 297, + 297 : { + fsm_297.in = 1'd1; + } => 298, + 298 : { + fsm_298.in = 1'd1; + } => 299, + 299 : { + fsm_299.in = 1'd1; + } => 300, + 300 : { + fsm_300.in = 1'd1; + } => 301, + 301 : { + fsm_301.in = 1'd1; + } => 302, + 302 : { + fsm_302.in = 1'd1; + } => 303, + 303 : { + fsm_303.in = 1'd1; + } => 304, + 304 : { + fsm_304.in = 1'd1; + } => 305, + 305 : { + fsm_305.in = 1'd1; + } => 306, + 306 : { + fsm_306.in = 1'd1; + } => 307, + 307 : { + fsm_307.in = 1'd1; + } => 308, + 308 : { + fsm_308.in = 1'd1; + } => 309, + 309 : { + fsm_309.in = 1'd1; + } => 310, + 310 : { + fsm_310.in = 1'd1; + } => 311, + 311 : { + fsm_311.in = 1'd1; + } => 312, + 312 : { + fsm_312.in = 1'd1; + } => 313, + 313 : { + fsm_313.in = 1'd1; + } => 314, + 314 : { + fsm_314.in = 1'd1; + } => 315, + 315 : { + fsm_315.in = 1'd1; + } => 316, + 316 : { + fsm_316.in = 1'd1; + } => 317, + 317 : { + fsm_317.in = 1'd1; + } => 318, + 318 : { + fsm_318.in = 1'd1; + } => 319, + 319 : { + fsm_319.in = 1'd1; + } => 320, + 320 : { + fsm_320.in = 1'd1; + } => 321, + 321 : { + fsm_321.in = 1'd1; + } => 322, + 322 : { + fsm_322.in = 1'd1; + } => 323, + 323 : { + fsm_323.in = 1'd1; + } => 324, + 324 : { + fsm_324.in = 1'd1; + } => 325, + 325 : { + fsm_325.in = 1'd1; + } => 326, + 326 : { + fsm_326.in = 1'd1; + } => 327, + 327 : { + fsm_327.in = 1'd1; + } => 328, + 328 : { + fsm_328.in = 1'd1; + } => 329, + 329 : { + fsm_329.in = 1'd1; + } => 330, + 330 : { + fsm_330.in = 1'd1; + } => 331, + 331 : { + fsm_331.in = 1'd1; + } => 332, + 332 : { + fsm_332.in = 1'd1; + } => 333, + 333 : { + fsm_333.in = 1'd1; + } => 334, + 334 : { + fsm_334.in = 1'd1; + } => 335, + 335 : { + fsm_335.in = 1'd1; + } => 336, + 336 : { + fsm_336.in = 1'd1; + } => 337, + 337 : { + fsm_337.in = 1'd1; + } => 338, + 338 : { + fsm_338.in = 1'd1; + } => 339, + 339 : { + fsm_339.in = 1'd1; + } => 340, + 340 : { + fsm_340.in = 1'd1; + } => 341, + 341 : { + fsm_341.in = 1'd1; + } => 342, + 342 : { + fsm_342.in = 1'd1; + } => 343, + 343 : { + fsm_343.in = 1'd1; + } => 344, + 344 : { + fsm_344.in = 1'd1; + } => 345, + 345 : { + fsm_345.in = 1'd1; + } => 346, + 346 : { + fsm_346.in = 1'd1; + } => 347, + 347 : { + fsm_347.in = 1'd1; + } => 348, + 348 : { + fsm_348.in = 1'd1; + } => 349, + 349 : { + fsm_349.in = 1'd1; + } => 350, + 350 : { + fsm_350.in = 1'd1; + } => 351, + 351 : { + fsm_351.in = 1'd1; + } => 352, + 352 : { + fsm_352.in = 1'd1; + } => 353, + 353 : { + fsm_353.in = 1'd1; + } => 354, + 354 : { + fsm_354.in = 1'd1; + } => 355, + 355 : { + fsm_355.in = 1'd1; + } => 356, + 356 : { + fsm_356.in = 1'd1; + } => 357, + 357 : { + fsm_357.in = 1'd1; + } => 358, + 358 : { + fsm_358.in = 1'd1; + } => 359, + 359 : { + fsm_359.in = 1'd1; + } => 360, + 360 : { + fsm_360.in = 1'd1; + } => 361, + 361 : { + fsm_361.in = 1'd1; + } => 362, + 362 : { + fsm_362.in = 1'd1; + } => 363, + 363 : { + fsm_363.in = 1'd1; + } => 364, + 364 : { + fsm_364.in = 1'd1; + } => 365, + 365 : { + fsm_365.in = 1'd1; + } => 366, + 366 : { + fsm_366.in = 1'd1; + } => 367, + 367 : { + fsm_367.in = 1'd1; + } => 368, + 368 : { + fsm_368.in = 1'd1; + } => 369, + 369 : { + fsm_369.in = 1'd1; + } => 370, + 370 : { + fsm_370.in = 1'd1; + } => 371, + 371 : { + fsm_371.in = 1'd1; + } => 372, + 372 : { + fsm_372.in = 1'd1; + } => 373, + 373 : { + fsm_373.in = 1'd1; + } => 374, + 374 : { + fsm_374.in = 1'd1; + } => 375, + 375 : { + fsm_375.in = 1'd1; + } => 376, + 376 : { + fsm_376.in = 1'd1; + } => 377, + 377 : { + fsm_377.in = 1'd1; + } => 378, + 378 : { + fsm_378.in = 1'd1; + } => 379, + 379 : { + fsm_379.in = 1'd1; + } => 380, + 380 : { + fsm_380.in = 1'd1; + } => 381, + 381 : { + fsm_381.in = 1'd1; + } => 382, + 382 : { + fsm_382.in = 1'd1; + } => 383, + 383 : { + fsm_383.in = 1'd1; + } => 384, + 384 : { + fsm_384.in = 1'd1; + } => 385, + 385 : { + fsm_385.in = 1'd1; + } => 386, + 386 : { + fsm_386.in = 1'd1; + } => 387, + 387 : { + fsm_387.in = 1'd1; + } => 388, + 388 : { + fsm_388.in = 1'd1; + } => 389, + 389 : { + fsm_389.in = 1'd1; + } => 390, + 390 : { + fsm_390.in = 1'd1; + } => 391, + 391 : { + fsm_391.in = 1'd1; + } => 392, + 392 : { + fsm_392.in = 1'd1; + } => 393, + 393 : { + fsm_393.in = 1'd1; + } => 394, + 394 : { + fsm_394.in = 1'd1; + } => 395, + 395 : { + fsm_395.in = 1'd1; + } => 396, + 396 : { + fsm_396.in = 1'd1; + } => 397, + 397 : { + fsm_397.in = 1'd1; + } => 398, + 398 : { + fsm_398.in = 1'd1; + } => 399, + 399 : { + fsm_399.in = 1'd1; + } => 400, + 400 : { + fsm_400.in = 1'd1; + } => 401, + 401 : { + fsm_401.in = 1'd1; + } => 402, + 402 : { + fsm_402.in = 1'd1; + } => 403, + 403 : { + fsm_403.in = 1'd1; + } => 404, + 404 : { + fsm_404.in = 1'd1; + } => 405, + 405 : { + fsm_405.in = 1'd1; + } => 406, + 406 : { + fsm_406.in = 1'd1; + } => 407, + 407 : { + fsm_407.in = 1'd1; + } => 408, + 408 : { + fsm_408.in = 1'd1; + } => 409, + 409 : { + fsm_409.in = 1'd1; + } => 410, + 410 : { + fsm_410.in = 1'd1; + } => 411, + 411 : { + fsm_411.in = 1'd1; + } => 412, + 412 : { + fsm_412.in = 1'd1; + } => 413, + 413 : { + fsm_413.in = 1'd1; + } => 414, + 414 : { + fsm_414.in = 1'd1; + } => 415, + 415 : { + fsm_415.in = 1'd1; + } => 416, + 416 : { + fsm_416.in = 1'd1; + } => 417, + 417 : { + fsm_417.in = 1'd1; + } => 418, + 418 : { + fsm_418.in = 1'd1; + } => 419, + 419 : { + fsm_419.in = 1'd1; + } => 420, + 420 : { + fsm_420.in = 1'd1; + } => 421, + 421 : { + fsm_421.in = 1'd1; + } => 422, + 422 : { + fsm_422.in = 1'd1; + } => 423, + 423 : { + fsm_423.in = 1'd1; + } => 424, + 424 : { + fsm_424.in = 1'd1; + } => 425, + 425 : { + fsm_425.in = 1'd1; + } => 426, + 426 : { + fsm_426.in = 1'd1; + } => 427, + 427 : { + fsm_427.in = 1'd1; + } => 428, + 428 : { + fsm_428.in = 1'd1; + } => 429, + 429 : { + fsm_429.in = 1'd1; + } => 430, + 430 : { + fsm_430.in = 1'd1; + } => 431, + 431 : { + fsm_431.in = 1'd1; + } => 432, + 432 : { + fsm_432.in = 1'd1; + } => 433, + 433 : { + fsm_433.in = 1'd1; + } => 434, + 434 : { + fsm_434.in = 1'd1; + } => 435, + 435 : { + fsm_435.in = 1'd1; + } => 436, + 436 : { + fsm_436.in = 1'd1; + } => 437, + 437 : { + fsm_437.in = 1'd1; + } => 438, + 438 : { + fsm_438.in = 1'd1; + } => 439, + 439 : { + fsm_439.in = 1'd1; + } => 440, + 440 : { + fsm_440.in = 1'd1; + } => 441, + 441 : { + fsm_441.in = 1'd1; + } => 442, + 442 : { + fsm_442.in = 1'd1; + } => 443, + 443 : { + fsm_443.in = 1'd1; + } => 444, + 444 : { + fsm_444.in = 1'd1; + } => 445, + 445 : { + fsm_445.in = 1'd1; + } => 446, + 446 : { + fsm_446.in = 1'd1; + } => 447, + 447 : { + fsm_447.in = 1'd1; + } => 448, + 448 : { + fsm_448.in = 1'd1; + } => 449, + 449 : { + fsm_449.in = 1'd1; + } => 0, + } + fsm fsm0 { + 0 : { + fsm0_0.in = fsm0[start] ? 1'd1; + looped_once0.in = fsm0[start] ? 1'd1; + looped_once0.write_en = 1'd1; + fsm0[done] = looped_once0.out; + } => { + group_counter.out == const449999999_29_.out & fsm0[start] -> 1, + default -> 0, + }, + 1 : { + fsm0_1.in = 1'd1; + } => 0, + } + mult.left = fsm_2.out | fsm_3.out | fsm_4.out | fsm_12.out | fsm_13.out | fsm_14.out | fsm_22.out | fsm_23.out | fsm_24.out | fsm_32.out | fsm_33.out | fsm_34.out | fsm_42.out | fsm_43.out | fsm_44.out | fsm_52.out | fsm_53.out | fsm_54.out | fsm_62.out | fsm_63.out | fsm_64.out | fsm_72.out | fsm_73.out | fsm_74.out | fsm_82.out | fsm_83.out | fsm_84.out | fsm_92.out | fsm_93.out | fsm_94.out | fsm_102.out | fsm_103.out | fsm_104.out | fsm_112.out | fsm_113.out | fsm_114.out | fsm_122.out | fsm_123.out | fsm_124.out | fsm_132.out | fsm_133.out | fsm_134.out | fsm_142.out | fsm_143.out | fsm_144.out | fsm_152.out | fsm_153.out | fsm_154.out | fsm_162.out | fsm_163.out | fsm_164.out | fsm_172.out | fsm_173.out | fsm_174.out | fsm_182.out | fsm_183.out | fsm_184.out | fsm_192.out | fsm_193.out | fsm_194.out | fsm_202.out | fsm_203.out | fsm_204.out | fsm_212.out | fsm_213.out | fsm_214.out | fsm_222.out | fsm_223.out | fsm_224.out | fsm_232.out | fsm_233.out | fsm_234.out | fsm_242.out | fsm_243.out | fsm_244.out | fsm_252.out | fsm_253.out | fsm_254.out | fsm_262.out | fsm_263.out | fsm_264.out | fsm_272.out | fsm_273.out | fsm_274.out | fsm_282.out | fsm_283.out | fsm_284.out | fsm_292.out | fsm_293.out | fsm_294.out | fsm_302.out | fsm_303.out | fsm_304.out | fsm_312.out | fsm_313.out | fsm_314.out | fsm_322.out | fsm_323.out | fsm_324.out | fsm_332.out | fsm_333.out | fsm_334.out | fsm_342.out | fsm_343.out | fsm_344.out | fsm_352.out | fsm_353.out | fsm_354.out | fsm_362.out | fsm_363.out | fsm_364.out | fsm_372.out | fsm_373.out | fsm_374.out | fsm_382.out | fsm_383.out | fsm_384.out | fsm_392.out | fsm_393.out | fsm_394.out | fsm_402.out | fsm_403.out | fsm_404.out | fsm_412.out | fsm_413.out | fsm_414.out | fsm_422.out | fsm_423.out | fsm_424.out | fsm_432.out | fsm_433.out | fsm_434.out | fsm_442.out | fsm_443.out | fsm_444.out ? 2'd1; + mult.go = fsm_2.out | fsm_3.out | fsm_4.out | fsm_12.out | fsm_13.out | fsm_14.out | fsm_22.out | fsm_23.out | fsm_24.out | fsm_32.out | fsm_33.out | fsm_34.out | fsm_42.out | fsm_43.out | fsm_44.out | fsm_52.out | fsm_53.out | fsm_54.out | fsm_62.out | fsm_63.out | fsm_64.out | fsm_72.out | fsm_73.out | fsm_74.out | fsm_82.out | fsm_83.out | fsm_84.out | fsm_92.out | fsm_93.out | fsm_94.out | fsm_102.out | fsm_103.out | fsm_104.out | fsm_112.out | fsm_113.out | fsm_114.out | fsm_122.out | fsm_123.out | fsm_124.out | fsm_132.out | fsm_133.out | fsm_134.out | fsm_142.out | fsm_143.out | fsm_144.out | fsm_152.out | fsm_153.out | fsm_154.out | fsm_162.out | fsm_163.out | fsm_164.out | fsm_172.out | fsm_173.out | fsm_174.out | fsm_182.out | fsm_183.out | fsm_184.out | fsm_192.out | fsm_193.out | fsm_194.out | fsm_202.out | fsm_203.out | fsm_204.out | fsm_212.out | fsm_213.out | fsm_214.out | fsm_222.out | fsm_223.out | fsm_224.out | fsm_232.out | fsm_233.out | fsm_234.out | fsm_242.out | fsm_243.out | fsm_244.out | fsm_252.out | fsm_253.out | fsm_254.out | fsm_262.out | fsm_263.out | fsm_264.out | fsm_272.out | fsm_273.out | fsm_274.out | fsm_282.out | fsm_283.out | fsm_284.out | fsm_292.out | fsm_293.out | fsm_294.out | fsm_302.out | fsm_303.out | fsm_304.out | fsm_312.out | fsm_313.out | fsm_314.out | fsm_322.out | fsm_323.out | fsm_324.out | fsm_332.out | fsm_333.out | fsm_334.out | fsm_342.out | fsm_343.out | fsm_344.out | fsm_352.out | fsm_353.out | fsm_354.out | fsm_362.out | fsm_363.out | fsm_364.out | fsm_372.out | fsm_373.out | fsm_374.out | fsm_382.out | fsm_383.out | fsm_384.out | fsm_392.out | fsm_393.out | fsm_394.out | fsm_402.out | fsm_403.out | fsm_404.out | fsm_412.out | fsm_413.out | fsm_414.out | fsm_422.out | fsm_423.out | fsm_424.out | fsm_432.out | fsm_433.out | fsm_434.out | fsm_442.out | fsm_443.out | fsm_444.out ? 1'd1; + mult.right = fsm_2.out | fsm_3.out | fsm_4.out | fsm_12.out | fsm_13.out | fsm_14.out | fsm_22.out | fsm_23.out | fsm_24.out | fsm_32.out | fsm_33.out | fsm_34.out | fsm_42.out | fsm_43.out | fsm_44.out | fsm_52.out | fsm_53.out | fsm_54.out | fsm_62.out | fsm_63.out | fsm_64.out | fsm_72.out | fsm_73.out | fsm_74.out | fsm_82.out | fsm_83.out | fsm_84.out | fsm_92.out | fsm_93.out | fsm_94.out | fsm_102.out | fsm_103.out | fsm_104.out | fsm_112.out | fsm_113.out | fsm_114.out | fsm_122.out | fsm_123.out | fsm_124.out | fsm_132.out | fsm_133.out | fsm_134.out | fsm_142.out | fsm_143.out | fsm_144.out | fsm_152.out | fsm_153.out | fsm_154.out | fsm_162.out | fsm_163.out | fsm_164.out | fsm_172.out | fsm_173.out | fsm_174.out | fsm_182.out | fsm_183.out | fsm_184.out | fsm_192.out | fsm_193.out | fsm_194.out | fsm_202.out | fsm_203.out | fsm_204.out | fsm_212.out | fsm_213.out | fsm_214.out | fsm_222.out | fsm_223.out | fsm_224.out | fsm_232.out | fsm_233.out | fsm_234.out | fsm_242.out | fsm_243.out | fsm_244.out | fsm_252.out | fsm_253.out | fsm_254.out | fsm_262.out | fsm_263.out | fsm_264.out | fsm_272.out | fsm_273.out | fsm_274.out | fsm_282.out | fsm_283.out | fsm_284.out | fsm_292.out | fsm_293.out | fsm_294.out | fsm_302.out | fsm_303.out | fsm_304.out | fsm_312.out | fsm_313.out | fsm_314.out | fsm_322.out | fsm_323.out | fsm_324.out | fsm_332.out | fsm_333.out | fsm_334.out | fsm_342.out | fsm_343.out | fsm_344.out | fsm_352.out | fsm_353.out | fsm_354.out | fsm_362.out | fsm_363.out | fsm_364.out | fsm_372.out | fsm_373.out | fsm_374.out | fsm_382.out | fsm_383.out | fsm_384.out | fsm_392.out | fsm_393.out | fsm_394.out | fsm_402.out | fsm_403.out | fsm_404.out | fsm_412.out | fsm_413.out | fsm_414.out | fsm_422.out | fsm_423.out | fsm_424.out | fsm_432.out | fsm_433.out | fsm_434.out | fsm_442.out | fsm_443.out | fsm_444.out ? 2'd3; + fsm[start] = fsm0_0.out ? 1'd1; + adder.left = fsm0_0.out ? group_counter.out; + adder.right = fsm0_0.out ? 29'd1; + b.write_en = fsm_1.out | fsm_7.out | fsm_11.out | fsm_17.out | fsm_21.out | fsm_27.out | fsm_31.out | fsm_37.out | fsm_41.out | fsm_47.out | fsm_51.out | fsm_57.out | fsm_61.out | fsm_67.out | fsm_71.out | fsm_77.out | fsm_81.out | fsm_87.out | fsm_91.out | fsm_97.out | fsm_101.out | fsm_107.out | fsm_111.out | fsm_117.out | fsm_121.out | fsm_127.out | fsm_131.out | fsm_137.out | fsm_141.out | fsm_147.out | fsm_151.out | fsm_157.out | fsm_161.out | fsm_167.out | fsm_171.out | fsm_177.out | fsm_181.out | fsm_187.out | fsm_191.out | fsm_197.out | fsm_201.out | fsm_207.out | fsm_211.out | fsm_217.out | fsm_221.out | fsm_227.out | fsm_231.out | fsm_237.out | fsm_241.out | fsm_247.out | fsm_251.out | fsm_257.out | fsm_261.out | fsm_267.out | fsm_271.out | fsm_277.out | fsm_281.out | fsm_287.out | fsm_291.out | fsm_297.out | fsm_301.out | fsm_307.out | fsm_311.out | fsm_317.out | fsm_321.out | fsm_327.out | fsm_331.out | fsm_337.out | fsm_341.out | fsm_347.out | fsm_351.out | fsm_357.out | fsm_361.out | fsm_367.out | fsm_371.out | fsm_377.out | fsm_381.out | fsm_387.out | fsm_391.out | fsm_397.out | fsm_401.out | fsm_407.out | fsm_411.out | fsm_417.out | fsm_421.out | fsm_427.out | fsm_431.out | fsm_437.out | fsm_441.out | fsm_447.out ? 1'd1; + b.in = fsm_0.out | fsm_1.out | fsm_6.out | fsm_7.out | fsm_10.out | fsm_11.out | fsm_16.out | fsm_17.out | fsm_20.out | fsm_21.out | fsm_26.out | fsm_27.out | fsm_30.out | fsm_31.out | fsm_36.out | fsm_37.out | fsm_40.out | fsm_41.out | fsm_46.out | fsm_47.out | fsm_50.out | fsm_51.out | fsm_56.out | fsm_57.out | fsm_60.out | fsm_61.out | fsm_66.out | fsm_67.out | fsm_70.out | fsm_71.out | fsm_76.out | fsm_77.out | fsm_80.out | fsm_81.out | fsm_86.out | fsm_87.out | fsm_90.out | fsm_91.out | fsm_96.out | fsm_97.out | fsm_100.out | fsm_101.out | fsm_106.out | fsm_107.out | fsm_110.out | fsm_111.out | fsm_116.out | fsm_117.out | fsm_120.out | fsm_121.out | fsm_126.out | fsm_127.out | fsm_130.out | fsm_131.out | fsm_136.out | fsm_137.out | fsm_140.out | fsm_141.out | fsm_146.out | fsm_147.out | fsm_150.out | fsm_151.out | fsm_156.out | fsm_157.out | fsm_160.out | fsm_161.out | fsm_166.out | fsm_167.out | fsm_170.out | fsm_171.out | fsm_176.out | fsm_177.out | fsm_180.out | fsm_181.out | fsm_186.out | fsm_187.out | fsm_190.out | fsm_191.out | fsm_196.out | fsm_197.out | fsm_200.out | fsm_201.out | fsm_206.out | fsm_207.out | fsm_210.out | fsm_211.out | fsm_216.out | fsm_217.out | fsm_220.out | fsm_221.out | fsm_226.out | fsm_227.out | fsm_230.out | fsm_231.out | fsm_236.out | fsm_237.out | fsm_240.out | fsm_241.out | fsm_246.out | fsm_247.out | fsm_250.out | fsm_251.out | fsm_256.out | fsm_257.out | fsm_260.out | fsm_261.out | fsm_266.out | fsm_267.out | fsm_270.out | fsm_271.out | fsm_276.out | fsm_277.out | fsm_280.out | fsm_281.out | fsm_286.out | fsm_287.out | fsm_290.out | fsm_291.out | fsm_296.out | fsm_297.out | fsm_300.out | fsm_301.out | fsm_306.out | fsm_307.out | fsm_310.out | fsm_311.out | fsm_316.out | fsm_317.out | fsm_320.out | fsm_321.out | fsm_326.out | fsm_327.out | fsm_330.out | fsm_331.out | fsm_336.out | fsm_337.out | fsm_340.out | fsm_341.out | fsm_346.out | fsm_347.out | fsm_350.out | fsm_351.out | fsm_356.out | fsm_357.out | fsm_360.out | fsm_361.out | fsm_366.out | fsm_367.out | fsm_370.out | fsm_371.out | fsm_376.out | fsm_377.out | fsm_380.out | fsm_381.out | fsm_386.out | fsm_387.out | fsm_390.out | fsm_391.out | fsm_396.out | fsm_397.out | fsm_400.out | fsm_401.out | fsm_406.out | fsm_407.out | fsm_410.out | fsm_411.out | fsm_416.out | fsm_417.out | fsm_420.out | fsm_421.out | fsm_426.out | fsm_427.out | fsm_430.out | fsm_431.out | fsm_436.out | fsm_437.out | fsm_440.out | fsm_441.out | fsm_446.out | fsm_447.out ? 2'd1; + a.write_en = fsm_0.out | fsm_5.out | fsm_6.out | fsm_8.out | fsm_9.out | fsm_10.out | fsm_15.out | fsm_16.out | fsm_18.out | fsm_19.out | fsm_20.out | fsm_25.out | fsm_26.out | fsm_28.out | fsm_29.out | fsm_30.out | fsm_35.out | fsm_36.out | fsm_38.out | fsm_39.out | fsm_40.out | fsm_45.out | fsm_46.out | fsm_48.out | fsm_49.out | fsm_50.out | fsm_55.out | fsm_56.out | fsm_58.out | fsm_59.out | fsm_60.out | fsm_65.out | fsm_66.out | fsm_68.out | fsm_69.out | fsm_70.out | fsm_75.out | fsm_76.out | fsm_78.out | fsm_79.out | fsm_80.out | fsm_85.out | fsm_86.out | fsm_88.out | fsm_89.out | fsm_90.out | fsm_95.out | fsm_96.out | fsm_98.out | fsm_99.out | fsm_100.out | fsm_105.out | fsm_106.out | fsm_108.out | fsm_109.out | fsm_110.out | fsm_115.out | fsm_116.out | fsm_118.out | fsm_119.out | fsm_120.out | fsm_125.out | fsm_126.out | fsm_128.out | fsm_129.out | fsm_130.out | fsm_135.out | fsm_136.out | fsm_138.out | fsm_139.out | fsm_140.out | fsm_145.out | fsm_146.out | fsm_148.out | fsm_149.out | fsm_150.out | fsm_155.out | fsm_156.out | fsm_158.out | fsm_159.out | fsm_160.out | fsm_165.out | fsm_166.out | fsm_168.out | fsm_169.out | fsm_170.out | fsm_175.out | fsm_176.out | fsm_178.out | fsm_179.out | fsm_180.out | fsm_185.out | fsm_186.out | fsm_188.out | fsm_189.out | fsm_190.out | fsm_195.out | fsm_196.out | fsm_198.out | fsm_199.out | fsm_200.out | fsm_205.out | fsm_206.out | fsm_208.out | fsm_209.out | fsm_210.out | fsm_215.out | fsm_216.out | fsm_218.out | fsm_219.out | fsm_220.out | fsm_225.out | fsm_226.out | fsm_228.out | fsm_229.out | fsm_230.out | fsm_235.out | fsm_236.out | fsm_238.out | fsm_239.out | fsm_240.out | fsm_245.out | fsm_246.out | fsm_248.out | fsm_249.out | fsm_250.out | fsm_255.out | fsm_256.out | fsm_258.out | fsm_259.out | fsm_260.out | fsm_265.out | fsm_266.out | fsm_268.out | fsm_269.out | fsm_270.out | fsm_275.out | fsm_276.out | fsm_278.out | fsm_279.out | fsm_280.out | fsm_285.out | fsm_286.out | fsm_288.out | fsm_289.out | fsm_290.out | fsm_295.out | fsm_296.out | fsm_298.out | fsm_299.out | fsm_300.out | fsm_305.out | fsm_306.out | fsm_308.out | fsm_309.out | fsm_310.out | fsm_315.out | fsm_316.out | fsm_318.out | fsm_319.out | fsm_320.out | fsm_325.out | fsm_326.out | fsm_328.out | fsm_329.out | fsm_330.out | fsm_335.out | fsm_336.out | fsm_338.out | fsm_339.out | fsm_340.out | fsm_345.out | fsm_346.out | fsm_348.out | fsm_349.out | fsm_350.out | fsm_355.out | fsm_356.out | fsm_358.out | fsm_359.out | fsm_360.out | fsm_365.out | fsm_366.out | fsm_368.out | fsm_369.out | fsm_370.out | fsm_375.out | fsm_376.out | fsm_378.out | fsm_379.out | fsm_380.out | fsm_385.out | fsm_386.out | fsm_388.out | fsm_389.out | fsm_390.out | fsm_395.out | fsm_396.out | fsm_398.out | fsm_399.out | fsm_400.out | fsm_405.out | fsm_406.out | fsm_408.out | fsm_409.out | fsm_410.out | fsm_415.out | fsm_416.out | fsm_418.out | fsm_419.out | fsm_420.out | fsm_425.out | fsm_426.out | fsm_428.out | fsm_429.out | fsm_430.out | fsm_435.out | fsm_436.out | fsm_438.out | fsm_439.out | fsm_440.out | fsm_445.out | fsm_446.out | fsm_448.out | fsm_449.out | fsm0_1.out ? 1'd1; + a.in = fsm_0.out | fsm_1.out | fsm_6.out | fsm_7.out | fsm_10.out | fsm_11.out | fsm_16.out | fsm_17.out | fsm_20.out | fsm_21.out | fsm_26.out | fsm_27.out | fsm_30.out | fsm_31.out | fsm_36.out | fsm_37.out | fsm_40.out | fsm_41.out | fsm_46.out | fsm_47.out | fsm_50.out | fsm_51.out | fsm_56.out | fsm_57.out | fsm_60.out | fsm_61.out | fsm_66.out | fsm_67.out | fsm_70.out | fsm_71.out | fsm_76.out | fsm_77.out | fsm_80.out | fsm_81.out | fsm_86.out | fsm_87.out | fsm_90.out | fsm_91.out | fsm_96.out | fsm_97.out | fsm_100.out | fsm_101.out | fsm_106.out | fsm_107.out | fsm_110.out | fsm_111.out | fsm_116.out | fsm_117.out | fsm_120.out | fsm_121.out | fsm_126.out | fsm_127.out | fsm_130.out | fsm_131.out | fsm_136.out | fsm_137.out | fsm_140.out | fsm_141.out | fsm_146.out | fsm_147.out | fsm_150.out | fsm_151.out | fsm_156.out | fsm_157.out | fsm_160.out | fsm_161.out | fsm_166.out | fsm_167.out | fsm_170.out | fsm_171.out | fsm_176.out | fsm_177.out | fsm_180.out | fsm_181.out | fsm_186.out | fsm_187.out | fsm_190.out | fsm_191.out | fsm_196.out | fsm_197.out | fsm_200.out | fsm_201.out | fsm_206.out | fsm_207.out | fsm_210.out | fsm_211.out | fsm_216.out | fsm_217.out | fsm_220.out | fsm_221.out | fsm_226.out | fsm_227.out | fsm_230.out | fsm_231.out | fsm_236.out | fsm_237.out | fsm_240.out | fsm_241.out | fsm_246.out | fsm_247.out | fsm_250.out | fsm_251.out | fsm_256.out | fsm_257.out | fsm_260.out | fsm_261.out | fsm_266.out | fsm_267.out | fsm_270.out | fsm_271.out | fsm_276.out | fsm_277.out | fsm_280.out | fsm_281.out | fsm_286.out | fsm_287.out | fsm_290.out | fsm_291.out | fsm_296.out | fsm_297.out | fsm_300.out | fsm_301.out | fsm_306.out | fsm_307.out | fsm_310.out | fsm_311.out | fsm_316.out | fsm_317.out | fsm_320.out | fsm_321.out | fsm_326.out | fsm_327.out | fsm_330.out | fsm_331.out | fsm_336.out | fsm_337.out | fsm_340.out | fsm_341.out | fsm_346.out | fsm_347.out | fsm_350.out | fsm_351.out | fsm_356.out | fsm_357.out | fsm_360.out | fsm_361.out | fsm_366.out | fsm_367.out | fsm_370.out | fsm_371.out | fsm_376.out | fsm_377.out | fsm_380.out | fsm_381.out | fsm_386.out | fsm_387.out | fsm_390.out | fsm_391.out | fsm_396.out | fsm_397.out | fsm_400.out | fsm_401.out | fsm_406.out | fsm_407.out | fsm_410.out | fsm_411.out | fsm_416.out | fsm_417.out | fsm_420.out | fsm_421.out | fsm_426.out | fsm_427.out | fsm_430.out | fsm_431.out | fsm_436.out | fsm_437.out | fsm_440.out | fsm_441.out | fsm_446.out | fsm_447.out ? 2'd0; + a.in = fsm_5.out | fsm_8.out | fsm_9.out | fsm_15.out | fsm_18.out | fsm_19.out | fsm_25.out | fsm_28.out | fsm_29.out | fsm_35.out | fsm_38.out | fsm_39.out | fsm_45.out | fsm_48.out | fsm_49.out | fsm_55.out | fsm_58.out | fsm_59.out | fsm_65.out | fsm_68.out | fsm_69.out | fsm_75.out | fsm_78.out | fsm_79.out | fsm_85.out | fsm_88.out | fsm_89.out | fsm_95.out | fsm_98.out | fsm_99.out | fsm_105.out | fsm_108.out | fsm_109.out | fsm_115.out | fsm_118.out | fsm_119.out | fsm_125.out | fsm_128.out | fsm_129.out | fsm_135.out | fsm_138.out | fsm_139.out | fsm_145.out | fsm_148.out | fsm_149.out | fsm_155.out | fsm_158.out | fsm_159.out | fsm_165.out | fsm_168.out | fsm_169.out | fsm_175.out | fsm_178.out | fsm_179.out | fsm_185.out | fsm_188.out | fsm_189.out | fsm_195.out | fsm_198.out | fsm_199.out | fsm_205.out | fsm_208.out | fsm_209.out | fsm_215.out | fsm_218.out | fsm_219.out | fsm_225.out | fsm_228.out | fsm_229.out | fsm_235.out | fsm_238.out | fsm_239.out | fsm_245.out | fsm_248.out | fsm_249.out | fsm_255.out | fsm_258.out | fsm_259.out | fsm_265.out | fsm_268.out | fsm_269.out | fsm_275.out | fsm_278.out | fsm_279.out | fsm_285.out | fsm_288.out | fsm_289.out | fsm_295.out | fsm_298.out | fsm_299.out | fsm_305.out | fsm_308.out | fsm_309.out | fsm_315.out | fsm_318.out | fsm_319.out | fsm_325.out | fsm_328.out | fsm_329.out | fsm_335.out | fsm_338.out | fsm_339.out | fsm_345.out | fsm_348.out | fsm_349.out | fsm_355.out | fsm_358.out | fsm_359.out | fsm_365.out | fsm_368.out | fsm_369.out | fsm_375.out | fsm_378.out | fsm_379.out | fsm_385.out | fsm_388.out | fsm_389.out | fsm_395.out | fsm_398.out | fsm_399.out | fsm_405.out | fsm_408.out | fsm_409.out | fsm_415.out | fsm_418.out | fsm_419.out | fsm_425.out | fsm_428.out | fsm_429.out | fsm_435.out | fsm_438.out | fsm_439.out | fsm_445.out | fsm_448.out | fsm_449.out | fsm0_1.out ? 2'd2; + const449999999_29_.in = fsm0_0.out ? 29'd449999999; + group_counter.write_en = fsm0_0.out ? 1'd1; + group_counter.in = group_counter.out != const449999999_29_.out & fsm0_0.out ? adder.out; + group_counter.in = group_counter.out == const449999999_29_.out & fsm0_0.out ? 29'd0; + } + control { + fsm0; + } +} diff --git a/tests/passes/med-fsm/static-seq-repeat-offload.futil b/tests/passes/med-fsm/static-seq-repeat-offload.futil new file mode 100644 index 0000000000..613b8a0004 --- /dev/null +++ b/tests/passes/med-fsm/static-seq-repeat-offload.futil @@ -0,0 +1,321 @@ +// -p med-fsm +import "primitives/core.futil"; +import "primitives/memories/comb.futil"; +import "primitives/binary_operators.futil"; + +component main() -> () { + cells { + a = std_reg(2); + mult = std_mult_pipe(2); + b = std_reg(2); + c = std_reg(2); + d = std_reg(2); + r1 = std_reg(1); + } + + wires { + static<2> group A { + a.in = 2'd0; + a.write_en = %0 ? 1'd1; + b.in = 2'd1; + b.write_en = %1 ? 1'd1; + } + + static<3> group A3 { + mult.left = 2'd1; + mult.right = 2'd3; + mult.go = 1'd1; + } + + static<1> group C { + c.in = 2'd2; + c.write_en = %0 ? 1'd1; + } + + static<1> group D{ + c.in = 2'd2; + c.write_en = %0 ? 1'd1; + } + + } + + control { + static seq { + static repeat 1000000 { + static seq { + A; + A3; + C; + A; + C; + D; + A; + A3; + C; + A; + C; + D; + A; + A3; + C; + A; + C; + D; + A; + A3; + C; + A; + C; + D; + A; + A3; + C; + A; + C; + D; + A; + A3; + C; + A; + C; + D; + A; + A3; + C; + A; + C; + D; + A; + A3; + C; + A; + C; + D; + A; + A3; + C; + A; + C; + D; + A; + A3; + C; + A; + C; + D; + A; + A3; + C; + A; + C; + D; + A; + A3; + C; + A; + C; + D; + A; + A3; + C; + A; + C; + D; + A; + A3; + C; + A; + C; + D; + A; + A3; + C; + A; + C; + D; + A; + A3; + C; + A; + C; + D; + A; + A3; + C; + A; + C; + D; + A; + A3; + C; + A; + C; + D; + A; + A3; + C; + A; + C; + D; + A; + A3; + C; + A; + C; + D; + A; + A3; + C; + A; + C; + D; + A; + A3; + C; + A; + C; + D; + A; + A3; + C; + A; + C; + D; + A; + A3; + C; + A; + C; + D; + A; + A3; + C; + A; + C; + D; + A; + A3; + C; + A; + C; + D; + A; + A3; + C; + A; + C; + D; + A; + A3; + C; + A; + C; + D; + A; + A3; + C; + A; + C; + D; + A; + A3; + C; + A; + C; + D; + A; + A3; + C; + A; + C; + D; + A; + A3; + C; + A; + C; + D; + A; + A3; + C; + A; + C; + D; + A; + A3; + C; + A; + C; + D; + A; + A3; + C; + A; + C; + D; + A; + A3; + C; + A; + C; + D; + A; + A3; + C; + A; + C; + D; + A; + A3; + C; + A; + C; + D; + A; + A3; + C; + A; + C; + D; + A; + A3; + C; + A; + C; + D; + A; + A3; + C; + A; + C; + D; + A; + A3; + C; + A; + C; + D; + A; + A3; + C; + A; + C; + D; + A; + A3; + C; + A; + C; + D; + A; + A3; + C; + A; + C; + D; + } + } + D; + } + } +} \ No newline at end of file From 3e6d6e0ad16502c3004dce76608a370fc9cec8cb Mon Sep 17 00:00:00 2001 From: Cynthia Shao Date: Mon, 8 Dec 2025 14:10:27 -0500 Subject: [PATCH 6/8] finished ifs --- .../src/passes_experimental/fsm_builder.rs | 136 ++- inline.v | 961 +++++++++++++++ inline_parth.v | 1032 +++++++++++++++++ tests/passes/med-fsm/static-if-conds.expect | 43 + tests/passes/med-fsm/static-if-conds.futil | 39 + tests/passes/med-fsm/static-if-no-else.expect | 51 + tests/passes/med-fsm/static-if-no-else.futil | 24 + tests/passes/med-fsm/static-if-repeat.expect | 72 ++ tests/passes/med-fsm/static-if-repeat.futil | 40 + .../med-fsm/static-seq-repeat-offload.expect | 2 + 10 files changed, 2397 insertions(+), 3 deletions(-) create mode 100644 inline.v create mode 100644 inline_parth.v create mode 100644 tests/passes/med-fsm/static-if-conds.expect create mode 100644 tests/passes/med-fsm/static-if-conds.futil create mode 100644 tests/passes/med-fsm/static-if-no-else.expect create mode 100644 tests/passes/med-fsm/static-if-no-else.futil create mode 100644 tests/passes/med-fsm/static-if-repeat.expect create mode 100644 tests/passes/med-fsm/static-if-repeat.futil diff --git a/calyx/opt/src/passes_experimental/fsm_builder.rs b/calyx/opt/src/passes_experimental/fsm_builder.rs index c54543baf6..89080a3211 100644 --- a/calyx/opt/src/passes_experimental/fsm_builder.rs +++ b/calyx/opt/src/passes_experimental/fsm_builder.rs @@ -2,6 +2,8 @@ use crate::analysis::{IncompleteTransition, StaticSchedule}; use crate::traversal::{Action, ConstructVisitor, Named, Visitor}; use calyx_ir::{self as ir, GetAttributes}; use calyx_utils::CalyxResult; +use core::ops::Not; +use itertools::Itertools; const ACYCLIC: ir::Attribute = ir::Attribute::Internal(ir::InternalAttr::ACYCLIC); const UNROLL: ir::Attribute = ir::Attribute::Internal(ir::InternalAttr::UNROLL); @@ -152,7 +154,6 @@ impl StaticSchedule<'_, '_> { ir::StaticControl::Seq(sseq) => { if is_acyclic(sseq) && is_inline(sseq) { // @NUM_STATES(n) @ACYCLIC @INLINE - ( sseq.stmts.iter().enumerate().fold( transitions_to_curr, @@ -377,10 +378,40 @@ impl StaticSchedule<'_, '_> { ir::StaticControl::If(sif) => { if is_acyclic(sif) && is_inline(sif) { // @NUM_STATES(n) @ACYCLIC @INLINE - todo!() + // Both branches execute in parallel with conditional guards + let true_guard = + guard.clone().and(ir::Guard::port(sif.port.clone())); + let false_guard = guard + .clone() + .and(ir::Guard::not(ir::Guard::port(sif.port.clone()))); + + // Build both branches with their respective guards + ( + self.build_abstract( + &sif.tbranch, + true_guard, + transitions_to_curr.clone(), + looped_once_guard.clone(), + ) + .0 + .into_iter() + .chain( + self.build_abstract( + &sif.fbranch, + false_guard, + transitions_to_curr, + looped_once_guard, + ) + .0, + ) + .collect(), + None, + ) } else if is_offload(sif) { // @NUM_STATES(1) @OFFLOAD - todo!() + unreachable!( + "`build_abstract` encountered an impossible offload of Static Seq node." + ) } else { // we must have at least one `attr` annotation unreachable!( @@ -610,6 +641,105 @@ impl Visitor for FSMBuilder { } } + fn finish_static_if( + &mut self, + s: &mut calyx_ir::StaticIf, + comp: &mut calyx_ir::Component, + sigs: &calyx_ir::LibrarySignatures, + _comps: &[calyx_ir::Component], + ) -> crate::traversal::VisResult { + if is_offload(s) { + let non_promoted_static_component = comp.is_static() + && !(comp + .attributes + .has(ir::Attribute::Bool(ir::BoolAttr::Promoted))); + + let mut builder = ir::Builder::new(comp, sigs); + let signal_on = builder.add_constant(1, 1); + + // generate FSM for true branch + let mut sch_constructor_true = StaticSchedule::from(&mut builder); + let true_branch_fsm = sch_constructor_true.fsm_build( + &s.tbranch, + Component { + non_promoted_static_component: Some( + non_promoted_static_component, + ), + static_control_component: true, + }, + ); + + // group to active each FSM conditionally + let if_group = builder.add_static_group("if", s.latency); + let true_guard: ir::Guard = + ir::Guard::port(ir::RRC::clone(&s.port)); + let false_guard = ir::Guard::not(true_guard.clone()); + + // assignments to active each FSM + let mut trigger_fsms_with_branch_latency = vec![( + builder.build_assignment( + true_branch_fsm.borrow().get("start"), + signal_on.borrow().get("out"), + true_guard, + ), + s.tbranch.get_latency(), + )]; + + // generate FSM and start condition for false branch if branch not empty + if !(matches!(&*s.fbranch, ir::StaticControl::Empty(_))) { + let mut sch_constructor_false = + StaticSchedule::from(&mut builder); + let false_branch_fsm = sch_constructor_false.fsm_build( + &s.fbranch, + Component { + non_promoted_static_component: Some( + non_promoted_static_component, + ), + static_control_component: true, + }, + ); + trigger_fsms_with_branch_latency.push(( + builder.build_assignment( + false_branch_fsm.borrow().get("start"), + signal_on.borrow().get("out"), + false_guard, + ), + s.fbranch.get_latency(), + )); + } + + // make sure [start] for each FSM is pulsed at most once, at the first + // cycle + + let trigger_fsms = trigger_fsms_with_branch_latency + .into_iter() + .map(|(mut assign, latency)| { + assign + .guard + .add_interval(ir::StaticTiming::new((0, latency))); + assign + }) + .collect_vec(); + + if_group.borrow_mut().assignments.extend(trigger_fsms); + + // ensure this group only gets one state in the parent FSM, and only + // transitions out when the latency counter has completed + let mut enable = ir::StaticControl::Enable(ir::StaticEnable { + group: if_group, + attributes: ir::Attributes::default(), + }); + // enable + // .get_mut_attributes() + // .insert(ir::BoolAttr::OneState, 1); + + enable.get_mut_attributes().insert(INLINE, 1); + Ok(Action::static_change(enable)) + } else { + Ok(Action::Continue) + } + } + /// `finish_static_control` is called once, at the very end of traversing the control tree, /// when all child nodes have been traversed. We traverse the static control node from parent to /// child, and recurse inward to inline children. diff --git a/inline.v b/inline.v new file mode 100644 index 0000000000..dfa6c54f69 --- /dev/null +++ b/inline.v @@ -0,0 +1,961 @@ +module comb_mem_d1 #( + parameter WIDTH = 32, + parameter SIZE = 16, + parameter IDX_SIZE = 4 +) ( + input wire logic [IDX_SIZE-1:0] addr0, + input wire logic [ WIDTH-1:0] write_data, + input wire logic write_en, + input wire logic clk, + input wire logic reset, + output logic [ WIDTH-1:0] read_data, + output logic done +); + + logic [WIDTH-1:0] mem[SIZE-1:0]; + + /* verilator lint_off WIDTH */ + assign read_data = mem[addr0]; + + always_ff @(posedge clk) begin + if (reset) + done <= '0; + else if (write_en) + done <= '1; + else + done <= '0; + end + + always_ff @(posedge clk) begin + if (!reset && write_en) + mem[addr0] <= write_data; + end + + // Check for out of bounds access + `ifdef VERILATOR + always_comb begin + if (addr0 >= SIZE) + $error( + "comb_mem_d1: Out of bounds access\n", + "addr0: %0d\n", addr0, + "SIZE: %0d", SIZE + ); + end + `endif +endmodule + +module comb_mem_d2 #( + parameter WIDTH = 32, + parameter D0_SIZE = 16, + parameter D1_SIZE = 16, + parameter D0_IDX_SIZE = 4, + parameter D1_IDX_SIZE = 4 +) ( + input wire logic [D0_IDX_SIZE-1:0] addr0, + input wire logic [D1_IDX_SIZE-1:0] addr1, + input wire logic [ WIDTH-1:0] write_data, + input wire logic write_en, + input wire logic clk, + input wire logic reset, + output logic [ WIDTH-1:0] read_data, + output logic done +); + + /* verilator lint_off WIDTH */ + logic [WIDTH-1:0] mem[D0_SIZE-1:0][D1_SIZE-1:0]; + + assign read_data = mem[addr0][addr1]; + + always_ff @(posedge clk) begin + if (reset) + done <= '0; + else if (write_en) + done <= '1; + else + done <= '0; + end + + always_ff @(posedge clk) begin + if (!reset && write_en) + mem[addr0][addr1] <= write_data; + end + + // Check for out of bounds access + `ifdef VERILATOR + always_comb begin + if (addr0 >= D0_SIZE) + $error( + "comb_mem_d2: Out of bounds access\n", + "addr0: %0d\n", addr0, + "D0_SIZE: %0d", D0_SIZE + ); + if (addr1 >= D1_SIZE) + $error( + "comb_mem_d2: Out of bounds access\n", + "addr1: %0d\n", addr1, + "D1_SIZE: %0d", D1_SIZE + ); + end + `endif +endmodule + +module comb_mem_d3 #( + parameter WIDTH = 32, + parameter D0_SIZE = 16, + parameter D1_SIZE = 16, + parameter D2_SIZE = 16, + parameter D0_IDX_SIZE = 4, + parameter D1_IDX_SIZE = 4, + parameter D2_IDX_SIZE = 4 +) ( + input wire logic [D0_IDX_SIZE-1:0] addr0, + input wire logic [D1_IDX_SIZE-1:0] addr1, + input wire logic [D2_IDX_SIZE-1:0] addr2, + input wire logic [ WIDTH-1:0] write_data, + input wire logic write_en, + input wire logic clk, + input wire logic reset, + output logic [ WIDTH-1:0] read_data, + output logic done +); + + /* verilator lint_off WIDTH */ + logic [WIDTH-1:0] mem[D0_SIZE-1:0][D1_SIZE-1:0][D2_SIZE-1:0]; + + assign read_data = mem[addr0][addr1][addr2]; + + always_ff @(posedge clk) begin + if (reset) + done <= '0; + else if (write_en) + done <= '1; + else + done <= '0; + end + + always_ff @(posedge clk) begin + if (!reset && write_en) + mem[addr0][addr1][addr2] <= write_data; + end + + // Check for out of bounds access + `ifdef VERILATOR + always_comb begin + if (addr0 >= D0_SIZE) + $error( + "comb_mem_d3: Out of bounds access\n", + "addr0: %0d\n", addr0, + "D0_SIZE: %0d", D0_SIZE + ); + if (addr1 >= D1_SIZE) + $error( + "comb_mem_d3: Out of bounds access\n", + "addr1: %0d\n", addr1, + "D1_SIZE: %0d", D1_SIZE + ); + if (addr2 >= D2_SIZE) + $error( + "comb_mem_d3: Out of bounds access\n", + "addr2: %0d\n", addr2, + "D2_SIZE: %0d", D2_SIZE + ); + end + `endif +endmodule + +module comb_mem_d4 #( + parameter WIDTH = 32, + parameter D0_SIZE = 16, + parameter D1_SIZE = 16, + parameter D2_SIZE = 16, + parameter D3_SIZE = 16, + parameter D0_IDX_SIZE = 4, + parameter D1_IDX_SIZE = 4, + parameter D2_IDX_SIZE = 4, + parameter D3_IDX_SIZE = 4 +) ( + input wire logic [D0_IDX_SIZE-1:0] addr0, + input wire logic [D1_IDX_SIZE-1:0] addr1, + input wire logic [D2_IDX_SIZE-1:0] addr2, + input wire logic [D3_IDX_SIZE-1:0] addr3, + input wire logic [ WIDTH-1:0] write_data, + input wire logic write_en, + input wire logic clk, + input wire logic reset, + output logic [ WIDTH-1:0] read_data, + output logic done +); + + /* verilator lint_off WIDTH */ + logic [WIDTH-1:0] mem[D0_SIZE-1:0][D1_SIZE-1:0][D2_SIZE-1:0][D3_SIZE-1:0]; + + assign read_data = mem[addr0][addr1][addr2][addr3]; + + always_ff @(posedge clk) begin + if (reset) + done <= '0; + else if (write_en) + done <= '1; + else + done <= '0; + end + + always_ff @(posedge clk) begin + if (!reset && write_en) + mem[addr0][addr1][addr2][addr3] <= write_data; + end + + // Check for out of bounds access + `ifdef VERILATOR + always_comb begin + if (addr0 >= D0_SIZE) + $error( + "comb_mem_d4: Out of bounds access\n", + "addr0: %0d\n", addr0, + "D0_SIZE: %0d", D0_SIZE + ); + if (addr1 >= D1_SIZE) + $error( + "comb_mem_d4: Out of bounds access\n", + "addr1: %0d\n", addr1, + "D1_SIZE: %0d", D1_SIZE + ); + if (addr2 >= D2_SIZE) + $error( + "comb_mem_d4: Out of bounds access\n", + "addr2: %0d\n", addr2, + "D2_SIZE: %0d", D2_SIZE + ); + if (addr3 >= D3_SIZE) + $error( + "comb_mem_d4: Out of bounds access\n", + "addr3: %0d\n", addr3, + "D3_SIZE: %0d", D3_SIZE + ); + end + `endif +endmodule + +/** + * Core primitives for Calyx. + * Implements core primitives used by the compiler. + * + * Conventions: + * - All parameter names must be SNAKE_CASE and all caps. + * - Port names must be snake_case, no caps. + */ + +module std_slice #( + parameter IN_WIDTH = 32, + parameter OUT_WIDTH = 32 +) ( + input wire logic [ IN_WIDTH-1:0] in, + output logic [OUT_WIDTH-1:0] out +); + assign out = in[OUT_WIDTH-1:0]; + + `ifdef VERILATOR + always_comb begin + if (IN_WIDTH < OUT_WIDTH) + $error( + "std_slice: Input width less than output width\n", + "IN_WIDTH: %0d", IN_WIDTH, + "OUT_WIDTH: %0d", OUT_WIDTH + ); + end + `endif +endmodule + +module std_pad #( + parameter IN_WIDTH = 32, + parameter OUT_WIDTH = 32 +) ( + input wire logic [IN_WIDTH-1:0] in, + output logic [OUT_WIDTH-1:0] out +); + localparam EXTEND = OUT_WIDTH - IN_WIDTH; + assign out = { {EXTEND {1'b0}}, in}; + + `ifdef VERILATOR + always_comb begin + if (IN_WIDTH > OUT_WIDTH) + $error( + "std_pad: Output width less than input width\n", + "IN_WIDTH: %0d", IN_WIDTH, + "OUT_WIDTH: %0d", OUT_WIDTH + ); + end + `endif +endmodule + +module std_cat #( + parameter LEFT_WIDTH = 32, + parameter RIGHT_WIDTH = 32, + parameter OUT_WIDTH = 64 +) ( + input wire logic [LEFT_WIDTH-1:0] left, + input wire logic [RIGHT_WIDTH-1:0] right, + output logic [OUT_WIDTH-1:0] out +); + assign out = {left, right}; + + `ifdef VERILATOR + always_comb begin + if (LEFT_WIDTH + RIGHT_WIDTH != OUT_WIDTH) + $error( + "std_cat: Output width must equal sum of input widths\n", + "LEFT_WIDTH: %0d", LEFT_WIDTH, + "RIGHT_WIDTH: %0d", RIGHT_WIDTH, + "OUT_WIDTH: %0d", OUT_WIDTH + ); + end + `endif +endmodule + +module std_not #( + parameter WIDTH = 32 +) ( + input wire logic [WIDTH-1:0] in, + output logic [WIDTH-1:0] out +); + assign out = ~in; +endmodule + +module std_and #( + parameter WIDTH = 32 +) ( + input wire logic [WIDTH-1:0] left, + input wire logic [WIDTH-1:0] right, + output logic [WIDTH-1:0] out +); + assign out = left & right; +endmodule + +module std_or #( + parameter WIDTH = 32 +) ( + input wire logic [WIDTH-1:0] left, + input wire logic [WIDTH-1:0] right, + output logic [WIDTH-1:0] out +); + assign out = left | right; +endmodule + +module std_xor #( + parameter WIDTH = 32 +) ( + input wire logic [WIDTH-1:0] left, + input wire logic [WIDTH-1:0] right, + output logic [WIDTH-1:0] out +); + assign out = left ^ right; +endmodule + +module std_sub #( + parameter WIDTH = 32 +) ( + input wire logic [WIDTH-1:0] left, + input wire logic [WIDTH-1:0] right, + output logic [WIDTH-1:0] out +); + assign out = left - right; +endmodule + +module std_gt #( + parameter WIDTH = 32 +) ( + input wire logic [WIDTH-1:0] left, + input wire logic [WIDTH-1:0] right, + output logic out +); + assign out = left > right; +endmodule + +module std_lt #( + parameter WIDTH = 32 +) ( + input wire logic [WIDTH-1:0] left, + input wire logic [WIDTH-1:0] right, + output logic out +); + assign out = left < right; +endmodule + +module std_eq #( + parameter WIDTH = 32 +) ( + input wire logic [WIDTH-1:0] left, + input wire logic [WIDTH-1:0] right, + output logic out +); + assign out = left == right; +endmodule + +module std_neq #( + parameter WIDTH = 32 +) ( + input wire logic [WIDTH-1:0] left, + input wire logic [WIDTH-1:0] right, + output logic out +); + assign out = left != right; +endmodule + +module std_ge #( + parameter WIDTH = 32 +) ( + input wire logic [WIDTH-1:0] left, + input wire logic [WIDTH-1:0] right, + output logic out +); + assign out = left >= right; +endmodule + +module std_le #( + parameter WIDTH = 32 +) ( + input wire logic [WIDTH-1:0] left, + input wire logic [WIDTH-1:0] right, + output logic out +); + assign out = left <= right; +endmodule + +module std_rsh #( + parameter WIDTH = 32 +) ( + input wire logic [WIDTH-1:0] left, + input wire logic [WIDTH-1:0] right, + output logic [WIDTH-1:0] out +); + assign out = left >> right; +endmodule + +/// this primitive is intended to be used +/// for lowering purposes (not in source programs) +module std_mux #( + parameter WIDTH = 32 +) ( + input wire logic cond, + input wire logic [WIDTH-1:0] tru, + input wire logic [WIDTH-1:0] fal, + output logic [WIDTH-1:0] out +); + assign out = cond ? tru : fal; +endmodule + +module std_bit_slice #( + parameter IN_WIDTH = 32, + parameter START_IDX = 0, + parameter END_IDX = 31, + parameter OUT_WIDTH = 32 +)( + input wire logic [IN_WIDTH-1:0] in, + output logic [OUT_WIDTH-1:0] out +); + assign out = in[END_IDX:START_IDX]; + + `ifdef VERILATOR + always_comb begin + if (START_IDX < 0 || END_IDX > IN_WIDTH-1) + $error( + "std_bit_slice: Slice range out of bounds\n", + "IN_WIDTH: %0d", IN_WIDTH, + "START_IDX: %0d", START_IDX, + "END_IDX: %0d", END_IDX, + ); + end + `endif + +endmodule + +module std_skid_buffer #( + parameter WIDTH = 32 +)( + input wire logic [WIDTH-1:0] in, + input wire logic i_valid, + input wire logic i_ready, + input wire logic clk, + input wire logic reset, + output logic [WIDTH-1:0] out, + output logic o_valid, + output logic o_ready +); + logic [WIDTH-1:0] val; + logic bypass_rg; + always @(posedge clk) begin + // Reset + if (reset) begin + // Internal Registers + val <= '0; + bypass_rg <= 1'b1; + end + // Out of reset + else begin + // Bypass state + if (bypass_rg) begin + if (!i_ready && i_valid) begin + val <= in; // Data skid happened, store to buffer + bypass_rg <= 1'b0; // To skid mode + end + end + // Skid state + else begin + if (i_ready) begin + bypass_rg <= 1'b1; // Back to bypass mode + end + end + end + end + + assign o_ready = bypass_rg; + assign out = bypass_rg ? in : val; + assign o_valid = bypass_rg ? i_valid : 1'b1; +endmodule + +module std_bypass_reg #( + parameter WIDTH = 32 +)( + input wire logic [WIDTH-1:0] in, + input wire logic write_en, + input wire logic clk, + input wire logic reset, + output logic [WIDTH-1:0] out, + output logic done +); + logic [WIDTH-1:0] val; + assign out = write_en ? in : val; + + always_ff @(posedge clk) begin + if (reset) begin + val <= 0; + done <= 0; + end else if (write_en) begin + val <= in; + done <= 1'd1; + end else done <= 1'd0; + end +endmodule + +module undef #( + parameter WIDTH = 32 +) ( + output logic [WIDTH-1:0] out +); +assign out = 'x; +endmodule + +module std_const #( + parameter WIDTH = 32, + parameter VALUE = 32 +) ( + output logic [WIDTH-1:0] out +); +assign out = VALUE; +endmodule + +module std_wire #( + parameter WIDTH = 32 +) ( + input wire logic [WIDTH-1:0] in, + output logic [WIDTH-1:0] out +); +assign out = in; +endmodule + +module std_add #( + parameter WIDTH = 32 +) ( + input wire logic [WIDTH-1:0] left, + input wire logic [WIDTH-1:0] right, + output logic [WIDTH-1:0] out +); +assign out = left + right; +endmodule + +module std_lsh #( + parameter WIDTH = 32 +) ( + input wire logic [WIDTH-1:0] left, + input wire logic [WIDTH-1:0] right, + output logic [WIDTH-1:0] out +); +assign out = left << right; +endmodule + +module std_reg #( + parameter WIDTH = 32 +) ( + input wire logic [WIDTH-1:0] in, + input wire logic write_en, + input wire logic clk, + input wire logic reset, + output logic [WIDTH-1:0] out, + output logic done +); +always_ff @(posedge clk) begin + if (reset) begin + out <= 0; + done <= 0; + end else if (write_en) begin + out <= in; + done <= 1'd1; + end else done <= 1'd0; + end +endmodule + +module init_one_reg #( + parameter WIDTH = 32 +) ( + input wire logic [WIDTH-1:0] in, + input wire logic write_en, + input wire logic clk, + input wire logic reset, + output logic [WIDTH-1:0] out, + output logic done +); +always_ff @(posedge clk) begin + if (reset) begin + out <= 1; + done <= 0; + end else if (write_en) begin + out <= in; + done <= 1'd1; + end else done <= 1'd0; + end +endmodule + + +module fsm_main_def ( + input logic clk, + input logic reset, + + input logic fsm_start_out, + input logic repeat_lt_0_out, + output logic s0_out, + output logic s1_out, + output logic s2_out, + output logic s3_out, + output logic s4_out +); + + parameter s0 = 3'd0; + parameter s1 = 3'd1; + parameter s2 = 3'd2; + parameter s3 = 3'd3; + parameter s4 = 3'd4; + + logic [2:0] state_reg; + logic [2:0] state_next; + + always @(posedge clk) begin +if (reset) begin + state_reg <= s0; + end +else begin + state_reg <= state_next; +end + end + + always @(*) begin + state_next = s0; +case ( state_reg ) + s0: begin + s0_out = 1'b1; + s1_out = 1'b0; + s2_out = 1'b0; + s3_out = 1'b0; + s4_out = 1'b0; + if (fsm_start_out) begin + state_next = s1; + end + else begin + state_next = s0; + end + end + s1: begin + s0_out = 1'b0; + s1_out = 1'b1; + s2_out = 1'b0; + s3_out = 1'b0; + s4_out = 1'b0; + state_next = s2; + end + s2: begin + s0_out = 1'b0; + s1_out = 1'b0; + s2_out = 1'b1; + s3_out = 1'b0; + s4_out = 1'b0; + state_next = s3; + end + s3: begin + s0_out = 1'b0; + s1_out = 1'b0; + s2_out = 1'b0; + s3_out = 1'b1; + s4_out = 1'b0; + if (repeat_lt_0_out) begin + state_next = s0; + end + else if (~(repeat_lt_0_out)) begin + state_next = s4; + end + else begin + state_next = s3; + end + end + s4: begin + s0_out = 1'b0; + s1_out = 1'b0; + s2_out = 1'b0; + s3_out = 1'b0; + s4_out = 1'b1; + state_next = s0; + end + endcase + end +endmodule + +module main( + input logic go, + input logic clk, + input logic reset, + output logic done +); +// COMPONENT START: main +logic [1:0] a_in; +logic a_write_en; +logic a_clk; +logic a_reset; +logic [1:0] a_out; +logic a_done; +logic [1:0] b_in; +logic b_write_en; +logic b_clk; +logic b_reset; +logic [1:0] b_out; +logic b_done; +logic [19:0] repeat_counter_0_in; +logic repeat_counter_0_write_en; +logic repeat_counter_0_clk; +logic repeat_counter_0_reset; +logic [19:0] repeat_counter_0_out; +logic repeat_counter_0_done; +logic [19:0] repeat_incr_0_left; +logic [19:0] repeat_incr_0_right; +logic [19:0] repeat_incr_0_out; +logic [19:0] repeat_lt_0_left; +logic [19:0] repeat_lt_0_right; +logic repeat_lt_0_out; +logic fsm_0_in; +logic fsm_0_out; +logic fsm_1_in; +logic fsm_1_out; +logic fsm_2_in; +logic fsm_2_out; +logic fsm_3_in; +logic fsm_3_out; +logic fsm_4_in; +logic fsm_4_out; +logic looped_once_in; +logic looped_once_write_en; +logic looped_once_clk; +logic looped_once_reset; +logic looped_once_out; +logic looped_once_done; +logic fsm_start_in; +logic fsm_start_out; +logic fsm_done_in; +logic fsm_done_out; +std_reg # ( + .WIDTH(2) +) a ( + .clk(a_clk), + .done(a_done), + .in(a_in), + .out(a_out), + .reset(a_reset), + .write_en(a_write_en) +); +std_reg # ( + .WIDTH(2) +) b ( + .clk(b_clk), + .done(b_done), + .in(b_in), + .out(b_out), + .reset(b_reset), + .write_en(b_write_en) +); +std_reg # ( + .WIDTH(20) +) repeat_counter_0 ( + .clk(repeat_counter_0_clk), + .done(repeat_counter_0_done), + .in(repeat_counter_0_in), + .out(repeat_counter_0_out), + .reset(repeat_counter_0_reset), + .write_en(repeat_counter_0_write_en) +); +std_add # ( + .WIDTH(20) +) repeat_incr_0 ( + .left(repeat_incr_0_left), + .out(repeat_incr_0_out), + .right(repeat_incr_0_right) +); +std_lt # ( + .WIDTH(20) +) repeat_lt_0 ( + .left(repeat_lt_0_left), + .out(repeat_lt_0_out), + .right(repeat_lt_0_right) +); +std_wire # ( + .WIDTH(1) +) fsm_0 ( + .in(fsm_0_in), + .out(fsm_0_out) +); +std_wire # ( + .WIDTH(1) +) fsm_1 ( + .in(fsm_1_in), + .out(fsm_1_out) +); +std_wire # ( + .WIDTH(1) +) fsm_2 ( + .in(fsm_2_in), + .out(fsm_2_out) +); +std_wire # ( + .WIDTH(1) +) fsm_3 ( + .in(fsm_3_in), + .out(fsm_3_out) +); +std_wire # ( + .WIDTH(1) +) fsm_4 ( + .in(fsm_4_in), + .out(fsm_4_out) +); +std_reg # ( + .WIDTH(1) +) looped_once ( + .clk(looped_once_clk), + .done(looped_once_done), + .in(looped_once_in), + .out(looped_once_out), + .reset(looped_once_reset), + .write_en(looped_once_write_en) +); +std_wire # ( + .WIDTH(1) +) fsm_start ( + .in(fsm_start_in), + .out(fsm_start_out) +); +std_wire # ( + .WIDTH(1) +) fsm_done ( + .in(fsm_done_in), + .out(fsm_done_out) +); +logic fsm_s0_out; +logic fsm_s1_out; +logic fsm_s2_out; +logic fsm_s3_out; +logic fsm_s4_out; +fsm_main_def fsm ( + .s0_out(fsm_s0_out), + .s1_out(fsm_s1_out), + .s2_out(fsm_s2_out), + .s3_out(fsm_s3_out), + .s4_out(fsm_s4_out), + .* +); +assign fsm_0_in = + (fsm_s0_out & (fsm_start_out)) ? 1'd1 : + 1'd0; +assign looped_once_in = + (fsm_s0_out & (fsm_start_out)) ? 1'd1 : + 1'd0; +assign fsm_1_in = + fsm_s1_out ? 1'd1 : + 1'd0; +assign fsm_3_in = + fsm_s3_out ? 1'd1 : + 1'd0; +assign fsm_4_in = + fsm_s4_out ? 1'd1 : + 1'd0; +assign fsm_done_in = + fsm_s0_out ? looped_once_out : + 1'd0; +assign fsm_2_in = + fsm_s2_out ? 1'd1 : + 1'd0; +assign looped_once_write_en = + fsm_s0_out ? 1'd1 : + 1'd0; +wire _guard0 = 1; +wire _guard1 = fsm_done_out; +wire _guard2 = fsm_3_out; +wire _guard3 = fsm_3_out; +wire _guard4 = fsm_0_out; +wire _guard5 = fsm_1_out; +wire _guard6 = _guard4 | _guard5; +wire _guard7 = fsm_2_out; +wire _guard8 = _guard6 | _guard7; +wire _guard9 = fsm_3_out; +wire _guard10 = _guard8 | _guard9; +wire _guard11 = fsm_4_out; +wire _guard12 = _guard10 | _guard11; +wire _guard13 = fsm_1_out; +wire _guard14 = fsm_3_out; +wire _guard15 = _guard13 | _guard14; +wire _guard16 = fsm_4_out; +wire _guard17 = _guard15 | _guard16; +wire _guard18 = fsm_0_out; +wire _guard19 = fsm_2_out; +wire _guard20 = _guard18 | _guard19; +wire _guard21 = fsm_3_out; +wire _guard22 = fsm_3_out; +assign done = _guard1; +assign looped_once_clk = clk; +assign looped_once_reset = reset; +assign b_write_en = 1'd0; +assign b_clk = clk; +assign b_reset = reset; +assign repeat_incr_0_left = + _guard2 ? repeat_counter_0_out : + 20'd0; +assign repeat_incr_0_right = + _guard3 ? 20'd1 : + 20'd0; +assign a_write_en = _guard12; +assign a_clk = clk; +assign a_reset = reset; +assign a_in = + _guard17 ? 2'd1 : + _guard20 ? 2'd0 : + 'x; +always_ff @(posedge clk) begin + if(~$onehot0({_guard20, _guard17})) begin + $fatal(2, "Multiple assignment to port `a.in'."); +end +end +assign repeat_counter_0_write_en = _guard21; +assign repeat_counter_0_clk = clk; +assign repeat_counter_0_reset = reset; +assign repeat_counter_0_in = + _guard22 ? repeat_incr_0_out : + 20'd0; +assign repeat_lt_0_left = repeat_counter_0_out; +assign repeat_lt_0_right = 20'd999999; +assign fsm_start_in = go; +// COMPONENT END: main +endmodule diff --git a/inline_parth.v b/inline_parth.v new file mode 100644 index 0000000000..076d5e8dad --- /dev/null +++ b/inline_parth.v @@ -0,0 +1,1032 @@ +module comb_mem_d1 #( + parameter WIDTH = 32, + parameter SIZE = 16, + parameter IDX_SIZE = 4 +) ( + input wire logic [IDX_SIZE-1:0] addr0, + input wire logic [ WIDTH-1:0] write_data, + input wire logic write_en, + input wire logic clk, + input wire logic reset, + output logic [ WIDTH-1:0] read_data, + output logic done +); + + logic [WIDTH-1:0] mem[SIZE-1:0]; + + /* verilator lint_off WIDTH */ + assign read_data = mem[addr0]; + + always_ff @(posedge clk) begin + if (reset) + done <= '0; + else if (write_en) + done <= '1; + else + done <= '0; + end + + always_ff @(posedge clk) begin + if (!reset && write_en) + mem[addr0] <= write_data; + end + + // Check for out of bounds access + `ifdef VERILATOR + always_comb begin + if (addr0 >= SIZE) + $error( + "comb_mem_d1: Out of bounds access\n", + "addr0: %0d\n", addr0, + "SIZE: %0d", SIZE + ); + end + `endif +endmodule + +module comb_mem_d2 #( + parameter WIDTH = 32, + parameter D0_SIZE = 16, + parameter D1_SIZE = 16, + parameter D0_IDX_SIZE = 4, + parameter D1_IDX_SIZE = 4 +) ( + input wire logic [D0_IDX_SIZE-1:0] addr0, + input wire logic [D1_IDX_SIZE-1:0] addr1, + input wire logic [ WIDTH-1:0] write_data, + input wire logic write_en, + input wire logic clk, + input wire logic reset, + output logic [ WIDTH-1:0] read_data, + output logic done +); + + /* verilator lint_off WIDTH */ + logic [WIDTH-1:0] mem[D0_SIZE-1:0][D1_SIZE-1:0]; + + assign read_data = mem[addr0][addr1]; + + always_ff @(posedge clk) begin + if (reset) + done <= '0; + else if (write_en) + done <= '1; + else + done <= '0; + end + + always_ff @(posedge clk) begin + if (!reset && write_en) + mem[addr0][addr1] <= write_data; + end + + // Check for out of bounds access + `ifdef VERILATOR + always_comb begin + if (addr0 >= D0_SIZE) + $error( + "comb_mem_d2: Out of bounds access\n", + "addr0: %0d\n", addr0, + "D0_SIZE: %0d", D0_SIZE + ); + if (addr1 >= D1_SIZE) + $error( + "comb_mem_d2: Out of bounds access\n", + "addr1: %0d\n", addr1, + "D1_SIZE: %0d", D1_SIZE + ); + end + `endif +endmodule + +module comb_mem_d3 #( + parameter WIDTH = 32, + parameter D0_SIZE = 16, + parameter D1_SIZE = 16, + parameter D2_SIZE = 16, + parameter D0_IDX_SIZE = 4, + parameter D1_IDX_SIZE = 4, + parameter D2_IDX_SIZE = 4 +) ( + input wire logic [D0_IDX_SIZE-1:0] addr0, + input wire logic [D1_IDX_SIZE-1:0] addr1, + input wire logic [D2_IDX_SIZE-1:0] addr2, + input wire logic [ WIDTH-1:0] write_data, + input wire logic write_en, + input wire logic clk, + input wire logic reset, + output logic [ WIDTH-1:0] read_data, + output logic done +); + + /* verilator lint_off WIDTH */ + logic [WIDTH-1:0] mem[D0_SIZE-1:0][D1_SIZE-1:0][D2_SIZE-1:0]; + + assign read_data = mem[addr0][addr1][addr2]; + + always_ff @(posedge clk) begin + if (reset) + done <= '0; + else if (write_en) + done <= '1; + else + done <= '0; + end + + always_ff @(posedge clk) begin + if (!reset && write_en) + mem[addr0][addr1][addr2] <= write_data; + end + + // Check for out of bounds access + `ifdef VERILATOR + always_comb begin + if (addr0 >= D0_SIZE) + $error( + "comb_mem_d3: Out of bounds access\n", + "addr0: %0d\n", addr0, + "D0_SIZE: %0d", D0_SIZE + ); + if (addr1 >= D1_SIZE) + $error( + "comb_mem_d3: Out of bounds access\n", + "addr1: %0d\n", addr1, + "D1_SIZE: %0d", D1_SIZE + ); + if (addr2 >= D2_SIZE) + $error( + "comb_mem_d3: Out of bounds access\n", + "addr2: %0d\n", addr2, + "D2_SIZE: %0d", D2_SIZE + ); + end + `endif +endmodule + +module comb_mem_d4 #( + parameter WIDTH = 32, + parameter D0_SIZE = 16, + parameter D1_SIZE = 16, + parameter D2_SIZE = 16, + parameter D3_SIZE = 16, + parameter D0_IDX_SIZE = 4, + parameter D1_IDX_SIZE = 4, + parameter D2_IDX_SIZE = 4, + parameter D3_IDX_SIZE = 4 +) ( + input wire logic [D0_IDX_SIZE-1:0] addr0, + input wire logic [D1_IDX_SIZE-1:0] addr1, + input wire logic [D2_IDX_SIZE-1:0] addr2, + input wire logic [D3_IDX_SIZE-1:0] addr3, + input wire logic [ WIDTH-1:0] write_data, + input wire logic write_en, + input wire logic clk, + input wire logic reset, + output logic [ WIDTH-1:0] read_data, + output logic done +); + + /* verilator lint_off WIDTH */ + logic [WIDTH-1:0] mem[D0_SIZE-1:0][D1_SIZE-1:0][D2_SIZE-1:0][D3_SIZE-1:0]; + + assign read_data = mem[addr0][addr1][addr2][addr3]; + + always_ff @(posedge clk) begin + if (reset) + done <= '0; + else if (write_en) + done <= '1; + else + done <= '0; + end + + always_ff @(posedge clk) begin + if (!reset && write_en) + mem[addr0][addr1][addr2][addr3] <= write_data; + end + + // Check for out of bounds access + `ifdef VERILATOR + always_comb begin + if (addr0 >= D0_SIZE) + $error( + "comb_mem_d4: Out of bounds access\n", + "addr0: %0d\n", addr0, + "D0_SIZE: %0d", D0_SIZE + ); + if (addr1 >= D1_SIZE) + $error( + "comb_mem_d4: Out of bounds access\n", + "addr1: %0d\n", addr1, + "D1_SIZE: %0d", D1_SIZE + ); + if (addr2 >= D2_SIZE) + $error( + "comb_mem_d4: Out of bounds access\n", + "addr2: %0d\n", addr2, + "D2_SIZE: %0d", D2_SIZE + ); + if (addr3 >= D3_SIZE) + $error( + "comb_mem_d4: Out of bounds access\n", + "addr3: %0d\n", addr3, + "D3_SIZE: %0d", D3_SIZE + ); + end + `endif +endmodule + +/** + * Core primitives for Calyx. + * Implements core primitives used by the compiler. + * + * Conventions: + * - All parameter names must be SNAKE_CASE and all caps. + * - Port names must be snake_case, no caps. + */ + +module std_slice #( + parameter IN_WIDTH = 32, + parameter OUT_WIDTH = 32 +) ( + input wire logic [ IN_WIDTH-1:0] in, + output logic [OUT_WIDTH-1:0] out +); + assign out = in[OUT_WIDTH-1:0]; + + `ifdef VERILATOR + always_comb begin + if (IN_WIDTH < OUT_WIDTH) + $error( + "std_slice: Input width less than output width\n", + "IN_WIDTH: %0d", IN_WIDTH, + "OUT_WIDTH: %0d", OUT_WIDTH + ); + end + `endif +endmodule + +module std_pad #( + parameter IN_WIDTH = 32, + parameter OUT_WIDTH = 32 +) ( + input wire logic [IN_WIDTH-1:0] in, + output logic [OUT_WIDTH-1:0] out +); + localparam EXTEND = OUT_WIDTH - IN_WIDTH; + assign out = { {EXTEND {1'b0}}, in}; + + `ifdef VERILATOR + always_comb begin + if (IN_WIDTH > OUT_WIDTH) + $error( + "std_pad: Output width less than input width\n", + "IN_WIDTH: %0d", IN_WIDTH, + "OUT_WIDTH: %0d", OUT_WIDTH + ); + end + `endif +endmodule + +module std_cat #( + parameter LEFT_WIDTH = 32, + parameter RIGHT_WIDTH = 32, + parameter OUT_WIDTH = 64 +) ( + input wire logic [LEFT_WIDTH-1:0] left, + input wire logic [RIGHT_WIDTH-1:0] right, + output logic [OUT_WIDTH-1:0] out +); + assign out = {left, right}; + + `ifdef VERILATOR + always_comb begin + if (LEFT_WIDTH + RIGHT_WIDTH != OUT_WIDTH) + $error( + "std_cat: Output width must equal sum of input widths\n", + "LEFT_WIDTH: %0d", LEFT_WIDTH, + "RIGHT_WIDTH: %0d", RIGHT_WIDTH, + "OUT_WIDTH: %0d", OUT_WIDTH + ); + end + `endif +endmodule + +module std_not #( + parameter WIDTH = 32 +) ( + input wire logic [WIDTH-1:0] in, + output logic [WIDTH-1:0] out +); + assign out = ~in; +endmodule + +module std_and #( + parameter WIDTH = 32 +) ( + input wire logic [WIDTH-1:0] left, + input wire logic [WIDTH-1:0] right, + output logic [WIDTH-1:0] out +); + assign out = left & right; +endmodule + +module std_or #( + parameter WIDTH = 32 +) ( + input wire logic [WIDTH-1:0] left, + input wire logic [WIDTH-1:0] right, + output logic [WIDTH-1:0] out +); + assign out = left | right; +endmodule + +module std_xor #( + parameter WIDTH = 32 +) ( + input wire logic [WIDTH-1:0] left, + input wire logic [WIDTH-1:0] right, + output logic [WIDTH-1:0] out +); + assign out = left ^ right; +endmodule + +module std_sub #( + parameter WIDTH = 32 +) ( + input wire logic [WIDTH-1:0] left, + input wire logic [WIDTH-1:0] right, + output logic [WIDTH-1:0] out +); + assign out = left - right; +endmodule + +module std_gt #( + parameter WIDTH = 32 +) ( + input wire logic [WIDTH-1:0] left, + input wire logic [WIDTH-1:0] right, + output logic out +); + assign out = left > right; +endmodule + +module std_lt #( + parameter WIDTH = 32 +) ( + input wire logic [WIDTH-1:0] left, + input wire logic [WIDTH-1:0] right, + output logic out +); + assign out = left < right; +endmodule + +module std_eq #( + parameter WIDTH = 32 +) ( + input wire logic [WIDTH-1:0] left, + input wire logic [WIDTH-1:0] right, + output logic out +); + assign out = left == right; +endmodule + +module std_neq #( + parameter WIDTH = 32 +) ( + input wire logic [WIDTH-1:0] left, + input wire logic [WIDTH-1:0] right, + output logic out +); + assign out = left != right; +endmodule + +module std_ge #( + parameter WIDTH = 32 +) ( + input wire logic [WIDTH-1:0] left, + input wire logic [WIDTH-1:0] right, + output logic out +); + assign out = left >= right; +endmodule + +module std_le #( + parameter WIDTH = 32 +) ( + input wire logic [WIDTH-1:0] left, + input wire logic [WIDTH-1:0] right, + output logic out +); + assign out = left <= right; +endmodule + +module std_rsh #( + parameter WIDTH = 32 +) ( + input wire logic [WIDTH-1:0] left, + input wire logic [WIDTH-1:0] right, + output logic [WIDTH-1:0] out +); + assign out = left >> right; +endmodule + +/// this primitive is intended to be used +/// for lowering purposes (not in source programs) +module std_mux #( + parameter WIDTH = 32 +) ( + input wire logic cond, + input wire logic [WIDTH-1:0] tru, + input wire logic [WIDTH-1:0] fal, + output logic [WIDTH-1:0] out +); + assign out = cond ? tru : fal; +endmodule + +module std_bit_slice #( + parameter IN_WIDTH = 32, + parameter START_IDX = 0, + parameter END_IDX = 31, + parameter OUT_WIDTH = 32 +)( + input wire logic [IN_WIDTH-1:0] in, + output logic [OUT_WIDTH-1:0] out +); + assign out = in[END_IDX:START_IDX]; + + `ifdef VERILATOR + always_comb begin + if (START_IDX < 0 || END_IDX > IN_WIDTH-1) + $error( + "std_bit_slice: Slice range out of bounds\n", + "IN_WIDTH: %0d", IN_WIDTH, + "START_IDX: %0d", START_IDX, + "END_IDX: %0d", END_IDX, + ); + end + `endif + +endmodule + +module std_skid_buffer #( + parameter WIDTH = 32 +)( + input wire logic [WIDTH-1:0] in, + input wire logic i_valid, + input wire logic i_ready, + input wire logic clk, + input wire logic reset, + output logic [WIDTH-1:0] out, + output logic o_valid, + output logic o_ready +); + logic [WIDTH-1:0] val; + logic bypass_rg; + always @(posedge clk) begin + // Reset + if (reset) begin + // Internal Registers + val <= '0; + bypass_rg <= 1'b1; + end + // Out of reset + else begin + // Bypass state + if (bypass_rg) begin + if (!i_ready && i_valid) begin + val <= in; // Data skid happened, store to buffer + bypass_rg <= 1'b0; // To skid mode + end + end + // Skid state + else begin + if (i_ready) begin + bypass_rg <= 1'b1; // Back to bypass mode + end + end + end + end + + assign o_ready = bypass_rg; + assign out = bypass_rg ? in : val; + assign o_valid = bypass_rg ? i_valid : 1'b1; +endmodule + +module std_bypass_reg #( + parameter WIDTH = 32 +)( + input wire logic [WIDTH-1:0] in, + input wire logic write_en, + input wire logic clk, + input wire logic reset, + output logic [WIDTH-1:0] out, + output logic done +); + logic [WIDTH-1:0] val; + assign out = write_en ? in : val; + + always_ff @(posedge clk) begin + if (reset) begin + val <= 0; + done <= 0; + end else if (write_en) begin + val <= in; + done <= 1'd1; + end else done <= 1'd0; + end +endmodule + +module undef #( + parameter WIDTH = 32 +) ( + output logic [WIDTH-1:0] out +); +assign out = 'x; +endmodule + +module std_const #( + parameter WIDTH = 32, + parameter VALUE = 32 +) ( + output logic [WIDTH-1:0] out +); +assign out = VALUE; +endmodule + +module std_wire #( + parameter WIDTH = 32 +) ( + input wire logic [WIDTH-1:0] in, + output logic [WIDTH-1:0] out +); +assign out = in; +endmodule + +module std_add #( + parameter WIDTH = 32 +) ( + input wire logic [WIDTH-1:0] left, + input wire logic [WIDTH-1:0] right, + output logic [WIDTH-1:0] out +); +assign out = left + right; +endmodule + +module std_lsh #( + parameter WIDTH = 32 +) ( + input wire logic [WIDTH-1:0] left, + input wire logic [WIDTH-1:0] right, + output logic [WIDTH-1:0] out +); +assign out = left << right; +endmodule + +module std_reg #( + parameter WIDTH = 32 +) ( + input wire logic [WIDTH-1:0] in, + input wire logic write_en, + input wire logic clk, + input wire logic reset, + output logic [WIDTH-1:0] out, + output logic done +); +always_ff @(posedge clk) begin + if (reset) begin + out <= 0; + done <= 0; + end else if (write_en) begin + out <= in; + done <= 1'd1; + end else done <= 1'd0; + end +endmodule + +module init_one_reg #( + parameter WIDTH = 32 +) ( + input wire logic [WIDTH-1:0] in, + input wire logic write_en, + input wire logic clk, + input wire logic reset, + output logic [WIDTH-1:0] out, + output logic done +); +always_ff @(posedge clk) begin + if (reset) begin + out <= 1; + done <= 0; + end else if (write_en) begin + out <= in; + done <= 1'd1; + end else done <= 1'd0; + end +endmodule + + +module fsm_main_def ( + input logic clk, + input logic reset, + + input logic fsm_start_out, + output logic s0_out, + output logic s1_out, + output logic s2_out, + output logic s3_out +); + + parameter s0 = 2'd0; + parameter s1 = 2'd1; + parameter s2 = 2'd2; + parameter s3 = 2'd3; + + logic [1:0] state_reg; + logic [1:0] state_next; + + always @(posedge clk) begin +if (reset) begin + state_reg <= s0; + end +else begin + state_reg <= state_next; +end + end + + always @(*) begin + state_next = s0; +case ( state_reg ) + s0: begin + s0_out = 1'b1; + s1_out = 1'b0; + s2_out = 1'b0; + s3_out = 1'b0; + if (fsm_start_out) begin + state_next = s1; + end + else begin + state_next = s0; + end + end + s1: begin + s0_out = 1'b0; + s1_out = 1'b1; + s2_out = 1'b0; + s3_out = 1'b0; + state_next = s2; + end + s2: begin + s0_out = 1'b0; + s1_out = 1'b0; + s2_out = 1'b1; + s3_out = 1'b0; + state_next = s3; + end + s3: begin + s0_out = 1'b0; + s1_out = 1'b0; + s2_out = 1'b0; + s3_out = 1'b1; + state_next = s0; + end + endcase + end +endmodule + + +module fsm0_main_def ( + input logic clk, + input logic reset, + + input logic [21:0] group_counter_out, + input logic [21:0] const3999999_22__out, + input logic fsm0_start_out, + output logic s0_out, + output logic s1_out +); + + parameter s0 = 1'd0; + parameter s1 = 1'd1; + + logic [0:0] state_reg; + logic [0:0] state_next; + + always @(posedge clk) begin +if (reset) begin + state_reg <= s0; + end +else begin + state_reg <= state_next; +end + end + + always @(*) begin + state_next = s0; +case ( state_reg ) + s0: begin + s0_out = 1'b1; + s1_out = 1'b0; + if ((group_counter_out == const3999999_22__out) & (fsm0_start_out)) begin + state_next = s1; + end + else begin + state_next = s0; + end + end + s1: begin + s0_out = 1'b0; + s1_out = 1'b1; + state_next = s0; + end + endcase + end +endmodule + +module main( + input logic go, + input logic clk, + input logic reset, + output logic done +); +// COMPONENT START: main +logic [1:0] a_in; +logic a_write_en; +logic a_clk; +logic a_reset; +logic [1:0] a_out; +logic a_done; +logic [1:0] b_in; +logic b_write_en; +logic b_clk; +logic b_reset; +logic [1:0] b_out; +logic b_done; +logic fsm_0_in; +logic fsm_0_out; +logic fsm_1_in; +logic fsm_1_out; +logic fsm_2_in; +logic fsm_2_out; +logic fsm_3_in; +logic fsm_3_out; +logic [21:0] group_counter_in; +logic group_counter_write_en; +logic group_counter_clk; +logic group_counter_reset; +logic [21:0] group_counter_out; +logic group_counter_done; +logic [21:0] const3999999_22__in; +logic [21:0] const3999999_22__out; +logic [21:0] adder_left; +logic [21:0] adder_right; +logic [21:0] adder_out; +logic fsm0_0_in; +logic fsm0_0_out; +logic fsm0_1_in; +logic fsm0_1_out; +logic looped_once_in; +logic looped_once_write_en; +logic looped_once_clk; +logic looped_once_reset; +logic looped_once_out; +logic looped_once_done; +logic fsm_start_in; +logic fsm_start_out; +logic fsm_done_in; +logic fsm_done_out; +logic fsm0_start_in; +logic fsm0_start_out; +logic fsm0_done_in; +logic fsm0_done_out; +std_reg # ( + .WIDTH(2) +) a ( + .clk(a_clk), + .done(a_done), + .in(a_in), + .out(a_out), + .reset(a_reset), + .write_en(a_write_en) +); +std_reg # ( + .WIDTH(2) +) b ( + .clk(b_clk), + .done(b_done), + .in(b_in), + .out(b_out), + .reset(b_reset), + .write_en(b_write_en) +); +std_wire # ( + .WIDTH(1) +) fsm_0 ( + .in(fsm_0_in), + .out(fsm_0_out) +); +std_wire # ( + .WIDTH(1) +) fsm_1 ( + .in(fsm_1_in), + .out(fsm_1_out) +); +std_wire # ( + .WIDTH(1) +) fsm_2 ( + .in(fsm_2_in), + .out(fsm_2_out) +); +std_wire # ( + .WIDTH(1) +) fsm_3 ( + .in(fsm_3_in), + .out(fsm_3_out) +); +std_reg # ( + .WIDTH(22) +) group_counter ( + .clk(group_counter_clk), + .done(group_counter_done), + .in(group_counter_in), + .out(group_counter_out), + .reset(group_counter_reset), + .write_en(group_counter_write_en) +); +std_wire # ( + .WIDTH(22) +) const3999999_22_ ( + .in(const3999999_22__in), + .out(const3999999_22__out) +); +std_add # ( + .WIDTH(22) +) adder ( + .left(adder_left), + .out(adder_out), + .right(adder_right) +); +std_wire # ( + .WIDTH(1) +) fsm0_0 ( + .in(fsm0_0_in), + .out(fsm0_0_out) +); +std_wire # ( + .WIDTH(1) +) fsm0_1 ( + .in(fsm0_1_in), + .out(fsm0_1_out) +); +std_reg # ( + .WIDTH(1) +) looped_once ( + .clk(looped_once_clk), + .done(looped_once_done), + .in(looped_once_in), + .out(looped_once_out), + .reset(looped_once_reset), + .write_en(looped_once_write_en) +); +std_wire # ( + .WIDTH(1) +) fsm_start ( + .in(fsm_start_in), + .out(fsm_start_out) +); +std_wire # ( + .WIDTH(1) +) fsm_done ( + .in(fsm_done_in), + .out(fsm_done_out) +); +std_wire # ( + .WIDTH(1) +) fsm0_start ( + .in(fsm0_start_in), + .out(fsm0_start_out) +); +std_wire # ( + .WIDTH(1) +) fsm0_done ( + .in(fsm0_done_in), + .out(fsm0_done_out) +); +logic fsm_s0_out; +logic fsm_s1_out; +logic fsm_s2_out; +logic fsm_s3_out; +fsm_main_def fsm ( + .s0_out(fsm_s0_out), + .s1_out(fsm_s1_out), + .s2_out(fsm_s2_out), + .s3_out(fsm_s3_out), + .* +); +logic fsm0_s0_out; +logic fsm0_s1_out; +fsm0_main_def fsm0 ( + .s0_out(fsm0_s0_out), + .s1_out(fsm0_s1_out), + .* +); +assign fsm_3_in = + fsm_s3_out ? 1'd1 : + 1'd0; +assign looped_once_in = + (fsm0_s0_out & ((fsm0_start_out) & (group_counter_out == const3999999_22__out))) ? 1'd1 : + 1'd0; +assign fsm_1_in = + fsm_s1_out ? 1'd1 : + 1'd0; +assign fsm0_done_in = + fsm0_s0_out ? looped_once_out : + 1'd0; +assign fsm_2_in = + fsm_s2_out ? 1'd1 : + 1'd0; +assign looped_once_write_en = + fsm0_s0_out ? 1'd1 : + 1'd0; +assign fsm0_1_in = + fsm0_s1_out ? 1'd1 : + 1'd0; +assign fsm0_0_in = + (fsm0_s0_out & (fsm0_start_out)) ? 1'd1 : + 1'd0; +assign fsm_0_in = + (fsm_s0_out & (fsm_start_out)) ? 1'd1 : + 1'd0; +wire _guard0 = 1; +wire _guard1 = fsm0_done_out; +wire _guard2 = fsm0_0_out; +wire _guard3 = fsm0_0_out; +wire _guard4 = fsm_2_out; +wire _guard5 = fsm_0_out; +wire _guard6 = _guard4 | _guard5; +wire _guard7 = fsm_1_out; +wire _guard8 = _guard6 | _guard7; +wire _guard9 = fsm_3_out; +wire _guard10 = _guard8 | _guard9; +wire _guard11 = fsm0_1_out; +wire _guard12 = _guard10 | _guard11; +wire _guard13 = fsm_1_out; +wire _guard14 = fsm_3_out; +wire _guard15 = _guard13 | _guard14; +wire _guard16 = fsm0_1_out; +wire _guard17 = _guard15 | _guard16; +wire _guard18 = fsm_2_out; +wire _guard19 = fsm_0_out; +wire _guard20 = _guard18 | _guard19; +wire _guard21 = fsm0_0_out; +wire _guard22 = group_counter_out != const3999999_22__out; +wire _guard23 = fsm0_0_out; +wire _guard24 = _guard22 & _guard23; +wire _guard25 = group_counter_out == const3999999_22__out; +wire _guard26 = fsm0_0_out; +wire _guard27 = _guard25 & _guard26; +wire _guard28 = fsm0_0_out; +wire _guard29 = fsm0_0_out; +assign done = _guard1; +assign adder_left = + _guard2 ? group_counter_out : + 22'd0; +assign adder_right = + _guard3 ? 22'd1 : + 22'd0; +assign looped_once_clk = clk; +assign looped_once_reset = reset; +assign fsm0_start_in = go; +assign b_write_en = 1'd0; +assign b_clk = clk; +assign b_reset = reset; +assign a_write_en = _guard12; +assign a_clk = clk; +assign a_reset = reset; +assign a_in = + _guard17 ? 2'd1 : + _guard20 ? 2'd0 : + 'x; +always_ff @(posedge clk) begin + if(~$onehot0({_guard20, _guard17})) begin + $fatal(2, "Multiple assignment to port `a.in'."); +end +end +assign group_counter_write_en = _guard21; +assign group_counter_clk = clk; +assign group_counter_reset = reset; +assign group_counter_in = + _guard24 ? adder_out : + _guard27 ? 22'd0 : + 22'd0; +always_ff @(posedge clk) begin + if(~$onehot0({_guard27, _guard24})) begin + $fatal(2, "Multiple assignment to port `group_counter.in'."); +end +end +assign const3999999_22__in = + _guard28 ? 22'd3999999 : + 22'd0; +assign fsm_start_in = _guard29; +// COMPONENT END: main +endmodule diff --git a/tests/passes/med-fsm/static-if-conds.expect b/tests/passes/med-fsm/static-if-conds.expect new file mode 100644 index 0000000000..806b00f78a --- /dev/null +++ b/tests/passes/med-fsm/static-if-conds.expect @@ -0,0 +1,43 @@ +import "primitives/core.futil"; +import "primitives/memories/comb.futil"; +component main(@go go: 1, @clk clk: 1, @reset reset: 1) -> (@done done: 1) { + cells { + @data t = std_reg(1); + @data f = std_reg(1); + @control lt = std_lt(1); + @generated comb_reg = std_reg(1); + @generated fsm_0 = std_wire(1); + @generated fsm_1 = std_wire(1); + @generated fsm_2 = std_wire(1); + @generated @fsm_control looped_once = std_reg(1); + } + wires { + fsm fsm { + 0 : { + fsm_0.in = fsm[start] ? 1'd1; + looped_once.in = fsm[start] ? 1'd1; + looped_once.write_en = 1'd1; + fsm[done] = looped_once.out; + } => { + comb_reg.out & fsm[start] -> 1, + !comb_reg.out & fsm[start] -> 2, + default -> 0, + }, + 1 : { + fsm_1.in = 1'd1; + } => 0, + 2 : { + fsm_2.in = 1'd1; + } => 0, + } + comb_reg.write_en = fsm_0.out ? 1'd1; + comb_reg.in = fsm_0.out ? lt.out; + t.write_en = comb_reg.out & fsm_1.out | !comb_reg.out & fsm_2.out ? 1'd1; + t.in = comb_reg.out & fsm_1.out | !comb_reg.out & fsm_2.out ? 1'd1; + lt.left = fsm_0.out ? 1'd1; + lt.right = fsm_0.out ? 1'd0; + } + control { + fsm; + } +} diff --git a/tests/passes/med-fsm/static-if-conds.futil b/tests/passes/med-fsm/static-if-conds.futil new file mode 100644 index 0000000000..8f82b23bad --- /dev/null +++ b/tests/passes/med-fsm/static-if-conds.futil @@ -0,0 +1,39 @@ +// -p med-fsm -x tdcc:infer-fsms + +import "primitives/core.futil"; +import "primitives/memories/comb.futil"; + +component main() -> () { + cells { + t = std_reg(1); + f = std_reg(1); + lt = std_lt(1); + } + + wires { + group true { + t.in = 1'b1; + t.write_en = 1'b1; + true[done] = t.done; + } + + group false { + f.in = 1'b1; + f.write_en = 1'b1; + false[done] = f.done; + } + + comb group cond { + lt.left = 1'b1; + lt.right = 1'b0; + } + } + + control { + if lt.out with cond { + true; + } else { + false; + } + } +} diff --git a/tests/passes/med-fsm/static-if-no-else.expect b/tests/passes/med-fsm/static-if-no-else.expect new file mode 100644 index 0000000000..5126082e34 --- /dev/null +++ b/tests/passes/med-fsm/static-if-no-else.expect @@ -0,0 +1,51 @@ +import "primitives/core.futil"; +import "primitives/memories/comb.futil"; +component main(@go go: 1, @clk clk: 1, @reset reset: 1) -> (@done done: 1) { + cells { + @data a = std_reg(2); + @data cond = std_reg(1); + @generated fsm_0 = std_wire(1); + @generated @fsm_control looped_once = std_reg(1); + @generated group_counter = std_reg(1); + @generated const0_1_ = std_wire(1); + @generated adder = std_add(1); + @generated fsm0_0 = std_wire(1); + @generated @fsm_control looped_once0 = std_reg(1); + } + wires { + fsm fsm { + 0 : { + fsm_0.in = fsm[start] ? 1'd1; + looped_once.in = fsm[start] ? 1'd1; + looped_once.write_en = 1'd1; + fsm[done] = looped_once.out; + } => { + fsm[start] -> 0, + default -> 0, + }, + } + fsm fsm0 { + 0 : { + fsm0_0.in = fsm0[start] ? 1'd1; + looped_once0.in = fsm0[start] ? 1'd1; + looped_once0.write_en = 1'd1; + fsm0[done] = looped_once0.out; + } => { + group_counter.out == const0_1_.out & fsm0[start] -> 0, + default -> 0, + }, + } + const0_1_.in = fsm0_0.out ? 1'd0; + fsm[start] = cond.out & 1'b1 & fsm0_0.out ? 1'd1; + adder.left = fsm0_0.out ? group_counter.out; + adder.right = fsm0_0.out ? 1'd1; + a.write_en = fsm_0.out ? 1'd1; + a.in = fsm_0.out ? 2'd0; + group_counter.write_en = fsm0_0.out ? 1'd1; + group_counter.in = group_counter.out != const0_1_.out & fsm0_0.out ? adder.out; + group_counter.in = group_counter.out == const0_1_.out & fsm0_0.out ? 1'd0; + } + control { + fsm0; + } +} diff --git a/tests/passes/med-fsm/static-if-no-else.futil b/tests/passes/med-fsm/static-if-no-else.futil new file mode 100644 index 0000000000..831a97eeaf --- /dev/null +++ b/tests/passes/med-fsm/static-if-no-else.futil @@ -0,0 +1,24 @@ +// -p med-fsm -x tdcc:infer-fsms + +import "primitives/core.futil"; +import "primitives/memories/comb.futil"; + +component main() -> () { + cells { + a = std_reg(2); + cond = std_reg(1); + } + + wires { + static<1> group A { + a.in = 2'd0; + a.write_en = %0 ? 1'd1; + } + } + + control { + static if cond.out { + A; + } + } +} \ No newline at end of file diff --git a/tests/passes/med-fsm/static-if-repeat.expect b/tests/passes/med-fsm/static-if-repeat.expect new file mode 100644 index 0000000000..d98e0a9d01 --- /dev/null +++ b/tests/passes/med-fsm/static-if-repeat.expect @@ -0,0 +1,72 @@ +import "primitives/core.futil"; +import "primitives/memories/comb.futil"; +component main(@go go: 1, @clk clk: 1, @reset reset: 1) -> (@done done: 1) { + cells { + @control lt = std_lt(1); + @data a = std_reg(2); + @data b = std_reg(2); + @generated comb_reg = std_reg(1); + @generated fsm_0 = std_wire(1); + @generated fsm_1 = std_wire(1); + @generated fsm_2 = std_wire(1); + @generated fsm_3 = std_wire(1); + @generated fsm_4 = std_wire(1); + @generated fsm_5 = std_wire(1); + @generated fsm_6 = std_wire(1); + @generated @fsm_control looped_once = std_reg(1); + } + wires { + fsm fsm { + 0 : { + fsm_0.in = fsm[start] ? 1'd1; + looped_once.in = fsm[start] ? 1'd1; + looped_once.write_en = 1'd1; + fsm[done] = looped_once.out; + } => { + comb_reg.out & fsm[start] -> 1, + !comb_reg.out & fsm[start] -> 4, + default -> 0, + }, + 1 : { + fsm_1.in = 1'd1; + } => { + comb_reg.out -> 2, + default -> 1, + }, + 2 : { + fsm_2.in = 1'd1; + } => { + comb_reg.out -> 3, + default -> 2, + }, + 3 : { + fsm_3.in = 1'd1; + } => 0, + 4 : { + fsm_4.in = 1'd1; + } => { + !comb_reg.out -> 5, + default -> 4, + }, + 5 : { + fsm_5.in = 1'd1; + } => { + !comb_reg.out -> 6, + default -> 5, + }, + 6 : { + fsm_6.in = 1'd1; + } => 0, + } + comb_reg.write_en = fsm_0.out ? 1'd1; + comb_reg.in = fsm_0.out ? lt.out; + a.write_en = comb_reg.out & fsm_1.out | comb_reg.out & fsm_2.out | comb_reg.out & fsm_3.out | !comb_reg.out & fsm_4.out | !comb_reg.out & fsm_5.out | !comb_reg.out & fsm_6.out ? 1'd1; + a.in = !comb_reg.out & fsm_4.out | !comb_reg.out & fsm_5.out | !comb_reg.out & fsm_6.out ? 2'd1; + a.in = comb_reg.out & fsm_1.out | comb_reg.out & fsm_2.out | comb_reg.out & fsm_3.out ? 2'd0; + lt.left = fsm_0.out ? 1'd1; + lt.right = fsm_0.out ? 1'd0; + } + control { + fsm; + } +} diff --git a/tests/passes/med-fsm/static-if-repeat.futil b/tests/passes/med-fsm/static-if-repeat.futil new file mode 100644 index 0000000000..b579353884 --- /dev/null +++ b/tests/passes/med-fsm/static-if-repeat.futil @@ -0,0 +1,40 @@ +// -p med-fsm -x tdcc:infer-fsms + +import "primitives/core.futil"; +import "primitives/memories/comb.futil"; + +component main() -> () { + cells { + lt = std_lt(1); + a = std_reg(2); + b = std_reg(2); + } + + wires { + comb group cond { + lt.left = 1'b1; + lt.right = 1'b0; + } + + static<1> group A { + a.in = 2'd0; + a.write_en = %0 ? 1'd1; + } + static<1> group B { + b.in = 2'd1; + b.write_en = %0 ? 1'd1; + } + } + + control { + if lt.out with cond { + static repeat 3{ + A; + } + } else { + static repeat 3{ + B; + } + } + } +} diff --git a/tests/passes/med-fsm/static-seq-repeat-offload.expect b/tests/passes/med-fsm/static-seq-repeat-offload.expect index a7b15d4f84..7c21061c55 100644 --- a/tests/passes/med-fsm/static-seq-repeat-offload.expect +++ b/tests/passes/med-fsm/static-seq-repeat-offload.expect @@ -1860,3 +1860,5 @@ component main(@go go: 1, @clk clk: 1, @reset reset: 1) -> (@done done: 1) { fsm0; } } +---STDERR--- +[WARN calyx_opt::pass_manager] fsm-builder: 14004ms From 65df6465ab964d960fc34ff7397a3fef05506b73 Mon Sep 17 00:00:00 2001 From: Cynthia Shao Date: Sat, 13 Dec 2025 17:10:41 -0500 Subject: [PATCH 7/8] disabled pass manager time warnings. Implemented first pass of par blocks. --- calyx/opt/src/pass_manager.rs | 2 +- .../src/passes_experimental/fsm_annotator.rs | 1 + .../src/passes_experimental/fsm_builder.rs | 62 +++- tests/passes/med-fsm/static-if-conds.expect | 261 ++++++++++++++ tests/passes/med-fsm/static-if-repeat.expect | 340 ++++++++++++++++-- tests/passes/med-fsm/static-if-repeat.futil | 8 +- .../med-fsm/static-seq-repeat-offload.expect | 2 - 7 files changed, 641 insertions(+), 35 deletions(-) diff --git a/calyx/opt/src/pass_manager.rs b/calyx/opt/src/pass_manager.rs index acd5ba81d9..61dc9ab075 100644 --- a/calyx/opt/src/pass_manager.rs +++ b/calyx/opt/src/pass_manager.rs @@ -291,7 +291,7 @@ impl PassManager { let elapsed = start.elapsed(); // Warn if pass takes more than 3 seconds. if elapsed.as_secs() > 5 { - log::warn!("{name}: {}ms", elapsed.as_millis()); + log::info!("{name}: {}ms", elapsed.as_millis()); } else { log::info!("{name}: {}ms", start.elapsed().as_millis()); } diff --git a/calyx/opt/src/passes_experimental/fsm_annotator.rs b/calyx/opt/src/passes_experimental/fsm_annotator.rs index 768358778d..bdafa6d94f 100644 --- a/calyx/opt/src/passes_experimental/fsm_annotator.rs +++ b/calyx/opt/src/passes_experimental/fsm_annotator.rs @@ -211,6 +211,7 @@ impl FSMPolicy for ir::StaticIf { fn policy(ctrl: &mut ir::StaticIf, _: u64) -> FSMImplementation { let (num_states, acyclic, attr) = if is_acyclic(&ctrl.tbranch) && is_acyclic(&ctrl.fbranch) { + dbg!(&ctrl.fbranch); ( ctrl.latency, true, diff --git a/calyx/opt/src/passes_experimental/fsm_builder.rs b/calyx/opt/src/passes_experimental/fsm_builder.rs index 89080a3211..bfd80e1be8 100644 --- a/calyx/opt/src/passes_experimental/fsm_builder.rs +++ b/calyx/opt/src/passes_experimental/fsm_builder.rs @@ -425,7 +425,9 @@ impl StaticSchedule<'_, '_> { todo!() } else if is_offload(spar) { // @NUM_STATES(1) @OFFLOAD - todo!() + unreachable!( + "`build_abstract` encountered an impossible offload of Static Seq node." + ) } else { // we must have at least one `attr` annotation unreachable!( @@ -446,7 +448,7 @@ impl StaticSchedule<'_, '_> { fn fsm_build( &mut self, control: &ir::StaticControl, - build_component_type: Component, // need to get better type name. Some(True) means non-promoted-static-component. False means promoted/static island. Otherwise it's a + build_component_type: Component, // need to get better type name. Some(True) means non-promoted-static-component. False means promoted/static island. Otherwise it's dynamic ) -> ir::RRC { let signal_on = self.builder.add_constant(1, 1); @@ -740,6 +742,62 @@ impl Visitor for FSMBuilder { } } + fn finish_static_par( + &mut self, + spar: &mut calyx_ir::StaticPar, + comp: &mut calyx_ir::Component, + sigs: &calyx_ir::LibrarySignatures, + _comps: &[calyx_ir::Component], + ) -> crate::traversal::VisResult { + let non_promoted_static_component = comp.is_static() + && !(comp + .attributes + .has(ir::Attribute::Bool(ir::BoolAttr::Promoted))); + if is_offload(spar) { + let mut builder = ir::Builder::new(comp, sigs); + let signal_on = builder.add_constant(1, 1); + let par_group = builder.add_static_group("par", spar.latency); + par_group + .borrow_mut() + .assignments + .extend(spar.stmts.iter().map(|thread: &ir::StaticControl| { + let mut sch_generator = StaticSchedule::from(&mut builder); + let thread_latency = thread.get_latency(); + let thread_fsm = sch_generator.fsm_build( + thread, + Component { + non_promoted_static_component: Some( + non_promoted_static_component, + ), + static_control_component: true, + }, + ); + let mut trigger_thread = builder.build_assignment( + thread_fsm.borrow().get("start"), + signal_on.borrow().get("out"), + ir::Guard::True, + ); + trigger_thread.guard.add_interval(ir::StaticTiming::new(( + 0, + thread_latency, + ))); + trigger_thread + })); + + let mut enable = ir::StaticControl::Enable(ir::StaticEnable { + group: par_group, + attributes: ir::Attributes::default(), + }); + // enable + // .get_mut_attributes() + // .insert(ir::BoolAttr::OneState, 1); + enable.get_mut_attributes().insert(INLINE, 1); + + Ok(Action::static_change(enable)) + } else { + Ok(Action::Continue) + } + } /// `finish_static_control` is called once, at the very end of traversing the control tree, /// when all child nodes have been traversed. We traverse the static control node from parent to /// child, and recurse inward to inline children. diff --git a/tests/passes/med-fsm/static-if-conds.expect b/tests/passes/med-fsm/static-if-conds.expect index 806b00f78a..0a0b6eff08 100644 --- a/tests/passes/med-fsm/static-if-conds.expect +++ b/tests/passes/med-fsm/static-if-conds.expect @@ -41,3 +41,264 @@ component main(@go go: 1, @clk clk: 1, @reset reset: 1) -> (@done done: 1) { fsm; } } +---STDERR--- +[calyx/opt/src/passes_experimental/fsm_annotator.rs:214:17] &ctrl.fbranch = Enable( + StaticEnable { + group: RefCell { + value: StaticGroup { + name: Id { + id: "invoke10", + }, + assignments: [ + Assignment { + dst: RefCell { + value: Port { + name: Id { + id: "write_en", + }, + width: 1, + direction: Input, + parent: Cell( + WRC { + internal: (Weak), + debug_name: Id { + id: "t", + }, + }, + ), + attributes: Attributes { + inl: InlineAttributes { + attrs: 0, + }, + hinfo: HeapAttrInfo { + attrs: { + Num( + WriteTogether, + ): 1, + Num( + Interval, + ): 1, + Num( + Go, + ): 1, + }, + set_attrs: {}, + span: GPosIdx( + PosIdx( + 0, + ), + ), + }, + }, + }, + }, + src: RefCell { + value: Port { + name: Id { + id: "out", + }, + width: 1, + direction: Output, + parent: Cell( + WRC { + internal: (Weak), + debug_name: Id { + id: "_1_1", + }, + }, + ), + attributes: Attributes { + inl: InlineAttributes { + attrs: 0, + }, + hinfo: HeapAttrInfo { + attrs: {}, + set_attrs: {}, + span: GPosIdx( + PosIdx( + 0, + ), + ), + }, + }, + }, + }, + guard: True, + attributes: Attributes { + inl: InlineAttributes { + attrs: 0, + }, + hinfo: HeapAttrInfo { + attrs: {}, + set_attrs: {}, + span: GPosIdx( + PosIdx( + 0, + ), + ), + }, + }, + }, + Assignment { + dst: RefCell { + value: Port { + name: Id { + id: "in", + }, + width: 1, + direction: Input, + parent: Cell( + WRC { + internal: (Weak), + debug_name: Id { + id: "t", + }, + }, + ), + attributes: Attributes { + inl: InlineAttributes { + attrs: 64, + }, + hinfo: HeapAttrInfo { + attrs: { + Num( + WriteTogether, + ): 1, + }, + set_attrs: {}, + span: GPosIdx( + PosIdx( + 0, + ), + ), + }, + }, + }, + }, + src: RefCell { + value: Port { + name: Id { + id: "out", + }, + width: 1, + direction: Output, + parent: Cell( + WRC { + internal: (Weak), + debug_name: Id { + id: "_1_1", + }, + }, + ), + attributes: Attributes { + inl: InlineAttributes { + attrs: 0, + }, + hinfo: HeapAttrInfo { + attrs: {}, + set_attrs: {}, + span: GPosIdx( + PosIdx( + 0, + ), + ), + }, + }, + }, + }, + guard: True, + attributes: Attributes { + inl: InlineAttributes { + attrs: 0, + }, + hinfo: HeapAttrInfo { + attrs: {}, + set_attrs: {}, + span: GPosIdx( + PosIdx( + 0, + ), + ), + }, + }, + }, + ], + holes: [ + RefCell { + value: Port { + name: Id { + id: "go", + }, + width: 1, + direction: Inout, + parent: StaticGroup( + WRC { + internal: (Weak), + debug_name: Id { + id: "invoke10", + }, + }, + ), + attributes: Attributes { + inl: InlineAttributes { + attrs: 0, + }, + hinfo: HeapAttrInfo { + attrs: {}, + set_attrs: {}, + span: GPosIdx( + PosIdx( + 0, + ), + ), + }, + }, + }, + }, + ], + attributes: Attributes { + inl: InlineAttributes { + attrs: 0, + }, + hinfo: HeapAttrInfo { + attrs: {}, + set_attrs: {}, + span: GPosIdx( + PosIdx( + 0, + ), + ), + }, + }, + latency: 1, + }, + }, + attributes: Attributes { + inl: InlineAttributes { + attrs: 0, + }, + hinfo: HeapAttrInfo { + attrs: { + Internal( + NODE_ID, + ): 2, + Internal( + NUM_STATES, + ): 1, + Internal( + INLINE, + ): 1, + Internal( + ACYCLIC, + ): 1, + }, + set_attrs: {}, + span: GPosIdx( + PosIdx( + 26, + ), + ), + }, + }, + }, +) diff --git a/tests/passes/med-fsm/static-if-repeat.expect b/tests/passes/med-fsm/static-if-repeat.expect index d98e0a9d01..6f8d028f2a 100644 --- a/tests/passes/med-fsm/static-if-repeat.expect +++ b/tests/passes/med-fsm/static-if-repeat.expect @@ -2,17 +2,15 @@ import "primitives/core.futil"; import "primitives/memories/comb.futil"; component main(@go go: 1, @clk clk: 1, @reset reset: 1) -> (@done done: 1) { cells { - @control lt = std_lt(1); + @data lt = std_lt(1); @data a = std_reg(2); @data b = std_reg(2); - @generated comb_reg = std_reg(1); @generated fsm_0 = std_wire(1); @generated fsm_1 = std_wire(1); @generated fsm_2 = std_wire(1); @generated fsm_3 = std_wire(1); @generated fsm_4 = std_wire(1); @generated fsm_5 = std_wire(1); - @generated fsm_6 = std_wire(1); @generated @fsm_control looped_once = std_reg(1); } wires { @@ -23,50 +21,342 @@ component main(@go go: 1, @clk clk: 1, @reset reset: 1) -> (@done done: 1) { looped_once.write_en = 1'd1; fsm[done] = looped_once.out; } => { - comb_reg.out & fsm[start] -> 1, - !comb_reg.out & fsm[start] -> 4, + lt.out & fsm[start] -> 1, default -> 0, }, 1 : { fsm_1.in = 1'd1; } => { - comb_reg.out -> 2, + lt.out -> 2, default -> 1, }, 2 : { fsm_2.in = 1'd1; - } => { - comb_reg.out -> 3, - default -> 2, - }, + } => 0, 3 : { fsm_3.in = 1'd1; - } => 0, + } => { + !lt.out -> 4, + default -> 3, + }, 4 : { fsm_4.in = 1'd1; } => { - !comb_reg.out -> 5, + !lt.out -> 5, default -> 4, }, 5 : { fsm_5.in = 1'd1; - } => { - !comb_reg.out -> 6, - default -> 5, - }, - 6 : { - fsm_6.in = 1'd1; } => 0, } - comb_reg.write_en = fsm_0.out ? 1'd1; - comb_reg.in = fsm_0.out ? lt.out; - a.write_en = comb_reg.out & fsm_1.out | comb_reg.out & fsm_2.out | comb_reg.out & fsm_3.out | !comb_reg.out & fsm_4.out | !comb_reg.out & fsm_5.out | !comb_reg.out & fsm_6.out ? 1'd1; - a.in = !comb_reg.out & fsm_4.out | !comb_reg.out & fsm_5.out | !comb_reg.out & fsm_6.out ? 2'd1; - a.in = comb_reg.out & fsm_1.out | comb_reg.out & fsm_2.out | comb_reg.out & fsm_3.out ? 2'd0; - lt.left = fsm_0.out ? 1'd1; - lt.right = fsm_0.out ? 1'd0; + a.write_en = lt.out & fsm_0.out | lt.out & fsm_1.out | lt.out & fsm_2.out | !lt.out & fsm_3.out | !lt.out & fsm_4.out | !lt.out & fsm_5.out ? 1'd1; + a.in = !lt.out & fsm_3.out | !lt.out & fsm_4.out | !lt.out & fsm_5.out ? 2'd1; + a.in = lt.out & fsm_0.out | lt.out & fsm_1.out | lt.out & fsm_2.out ? 2'd0; + lt.left = 1'd1; + lt.right = 1'd0; } control { fsm; } } +---STDERR--- +[calyx/opt/src/passes_experimental/fsm_annotator.rs:214:17] &ctrl.fbranch = Repeat( + StaticRepeat { + attributes: Attributes { + inl: InlineAttributes { + attrs: 0, + }, + hinfo: HeapAttrInfo { + attrs: { + Internal( + NODE_ID, + ): 3, + Internal( + NUM_STATES, + ): 3, + Internal( + UNROLL, + ): 1, + Internal( + ACYCLIC, + ): 1, + }, + set_attrs: {}, + span: GPosIdx( + PosIdx( + 24, + ), + ), + }, + }, + body: Enable( + StaticEnable { + group: RefCell { + value: StaticGroup { + name: Id { + id: "B", + }, + assignments: [ + Assignment { + dst: RefCell { + value: Port { + name: Id { + id: "in", + }, + width: 2, + direction: Input, + parent: Cell( + WRC { + internal: (Weak), + debug_name: Id { + id: "a", + }, + }, + ), + attributes: Attributes { + inl: InlineAttributes { + attrs: 64, + }, + hinfo: HeapAttrInfo { + attrs: { + Num( + WriteTogether, + ): 1, + }, + set_attrs: {}, + span: GPosIdx( + PosIdx( + 0, + ), + ), + }, + }, + }, + }, + src: RefCell { + value: Port { + name: Id { + id: "out", + }, + width: 2, + direction: Output, + parent: Cell( + WRC { + internal: (Weak), + debug_name: Id { + id: "_1_2", + }, + }, + ), + attributes: Attributes { + inl: InlineAttributes { + attrs: 0, + }, + hinfo: HeapAttrInfo { + attrs: {}, + set_attrs: {}, + span: GPosIdx( + PosIdx( + 0, + ), + ), + }, + }, + }, + }, + guard: True, + attributes: Attributes { + inl: InlineAttributes { + attrs: 0, + }, + hinfo: HeapAttrInfo { + attrs: {}, + set_attrs: {}, + span: GPosIdx( + PosIdx( + 17, + ), + ), + }, + }, + }, + Assignment { + dst: RefCell { + value: Port { + name: Id { + id: "write_en", + }, + width: 1, + direction: Input, + parent: Cell( + WRC { + internal: (Weak), + debug_name: Id { + id: "a", + }, + }, + ), + attributes: Attributes { + inl: InlineAttributes { + attrs: 0, + }, + hinfo: HeapAttrInfo { + attrs: { + Num( + WriteTogether, + ): 1, + Num( + Interval, + ): 1, + Num( + Go, + ): 1, + }, + set_attrs: {}, + span: GPosIdx( + PosIdx( + 0, + ), + ), + }, + }, + }, + }, + src: RefCell { + value: Port { + name: Id { + id: "out", + }, + width: 1, + direction: Output, + parent: Cell( + WRC { + internal: (Weak), + debug_name: Id { + id: "_1_1", + }, + }, + ), + attributes: Attributes { + inl: InlineAttributes { + attrs: 0, + }, + hinfo: HeapAttrInfo { + attrs: {}, + set_attrs: {}, + span: GPosIdx( + PosIdx( + 0, + ), + ), + }, + }, + }, + }, + guard: Info( + StaticTiming { + interval: ( + 0, + 1, + ), + }, + ), + attributes: Attributes { + inl: InlineAttributes { + attrs: 0, + }, + hinfo: HeapAttrInfo { + attrs: {}, + set_attrs: {}, + span: GPosIdx( + PosIdx( + 19, + ), + ), + }, + }, + }, + ], + holes: [ + RefCell { + value: Port { + name: Id { + id: "go", + }, + width: 1, + direction: Inout, + parent: StaticGroup( + WRC { + internal: (Weak), + debug_name: Id { + id: "B", + }, + }, + ), + attributes: Attributes { + inl: InlineAttributes { + attrs: 0, + }, + hinfo: HeapAttrInfo { + attrs: {}, + set_attrs: {}, + span: GPosIdx( + PosIdx( + 0, + ), + ), + }, + }, + }, + }, + ], + attributes: Attributes { + inl: InlineAttributes { + attrs: 0, + }, + hinfo: HeapAttrInfo { + attrs: {}, + set_attrs: {}, + span: GPosIdx( + PosIdx( + 16, + ), + ), + }, + }, + latency: 1, + }, + }, + attributes: Attributes { + inl: InlineAttributes { + attrs: 0, + }, + hinfo: HeapAttrInfo { + attrs: { + Internal( + NODE_ID, + ): 4, + Internal( + NUM_STATES, + ): 1, + Internal( + INLINE, + ): 1, + Internal( + ACYCLIC, + ): 1, + }, + set_attrs: {}, + span: GPosIdx( + PosIdx( + 25, + ), + ), + }, + }, + }, + ), + num_repeats: 3, + latency: 3, + }, +) diff --git a/tests/passes/med-fsm/static-if-repeat.futil b/tests/passes/med-fsm/static-if-repeat.futil index b579353884..0dd79ec0ce 100644 --- a/tests/passes/med-fsm/static-if-repeat.futil +++ b/tests/passes/med-fsm/static-if-repeat.futil @@ -11,10 +11,8 @@ component main() -> () { } wires { - comb group cond { - lt.left = 1'b1; - lt.right = 1'b0; - } + lt.left = 1'b1; + lt.right = 1'b0; static<1> group A { a.in = 2'd0; @@ -27,7 +25,7 @@ component main() -> () { } control { - if lt.out with cond { + static if lt.out { static repeat 3{ A; } diff --git a/tests/passes/med-fsm/static-seq-repeat-offload.expect b/tests/passes/med-fsm/static-seq-repeat-offload.expect index 7c21061c55..a7b15d4f84 100644 --- a/tests/passes/med-fsm/static-seq-repeat-offload.expect +++ b/tests/passes/med-fsm/static-seq-repeat-offload.expect @@ -1860,5 +1860,3 @@ component main(@go go: 1, @clk clk: 1, @reset reset: 1) -> (@done done: 1) { fsm0; } } ----STDERR--- -[WARN calyx_opt::pass_manager] fsm-builder: 14004ms From 5c9dbccce3456e651cd0e56892cc7bec500387b7 Mon Sep 17 00:00:00 2001 From: Cynthia Shao Date: Sun, 14 Dec 2025 16:01:51 -0500 Subject: [PATCH 8/8] fixed clippy formatter warnings --- .../src/passes_experimental/fsm_builder.rs | 22 +++++++++---------- 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/calyx/opt/src/passes_experimental/fsm_builder.rs b/calyx/opt/src/passes_experimental/fsm_builder.rs index bfd80e1be8..25db11ec5b 100644 --- a/calyx/opt/src/passes_experimental/fsm_builder.rs +++ b/calyx/opt/src/passes_experimental/fsm_builder.rs @@ -158,15 +158,13 @@ impl StaticSchedule<'_, '_> { sseq.stmts.iter().enumerate().fold( transitions_to_curr, |transitions_to_this_stmt, (_, stmt)| { - let result = self - .build_abstract( - stmt, - guard.clone(), - transitions_to_this_stmt, - looped_once_guard.clone(), - ) - .0; - result + self.build_abstract( + stmt, + guard.clone(), + transitions_to_this_stmt, + looped_once_guard.clone(), + ) + .0 }, ), None, @@ -261,7 +259,7 @@ impl StaticSchedule<'_, '_> { let counter_width = calyx_utils::math::bits_needed_for(srep.num_repeats); let counter = self.builder.add_primitive( - format!("repeat_counter_{}", loop_start_state), + format!("repeat_counter_{loop_start_state}"), "std_reg", &[counter_width], ); @@ -276,7 +274,7 @@ impl StaticSchedule<'_, '_> { // Increment counter on the last state of the loop body let incr = self.builder.add_primitive( - format!("repeat_incr_{}", loop_start_state), + format!("repeat_incr_{loop_start_state}"), "std_add", &[counter_width], ); @@ -319,7 +317,7 @@ impl StaticSchedule<'_, '_> { // Create guard: counter < num_repeats - 1 (loop condition) let lt = self.builder.add_primitive( - format!("repeat_lt_{}", loop_start_state), + format!("repeat_lt_{loop_start_state}"), "std_lt", &[counter_width], );