From c8e94f847bf3b9e8d804eab43c217efc8ac334d8 Mon Sep 17 00:00:00 2001 From: Pai Li Date: Thu, 27 Apr 2023 16:12:35 -0400 Subject: [PATCH 01/14] commit --- .vscode/settings.json | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index 5d2faa921b..b5b5e1f3d7 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -18,5 +18,8 @@ "python.analysis.typeCheckingMode": "basic", "python.analysis.inlayHints.variableTypes": true, "python.linting.flake8Enabled": true, - "jupyter.interactiveWindow.codeLens.enable": true + "jupyter.interactiveWindow.codeLens.enable": true, + "rust-analyzer.linkedProjects": [ + "./calyx-opt/Cargo.toml" + ] } \ No newline at end of file From 091be30cc8f3c6e0d72c5ffecac320d0de0e11fc Mon Sep 17 00:00:00 2001 From: Pai Li Date: Sun, 30 Apr 2023 15:21:52 -0400 Subject: [PATCH 02/14] static while --- calyx-opt/src/passes/compile_static.rs | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/calyx-opt/src/passes/compile_static.rs b/calyx-opt/src/passes/compile_static.rs index 55b57be332..5de4700664 100644 --- a/calyx-opt/src/passes/compile_static.rs +++ b/calyx-opt/src/passes/compile_static.rs @@ -346,6 +346,19 @@ impl Visitor for CompileStatic { Ok(Action::Change(Box::new(e))) } + fn finish_while( + &mut self, + s: &mut ir::While, + _comp: &mut ir::Component, + _sigs: &ir::LibrarySignatures, + _comps: &[ir::Component], + ) -> VisResult { + if (matches!(*(s.body), ir::Control::Static(_))) && s.cond.is_none() { + + } + Ok(Action::Continue) + } + fn finish( &mut self, comp: &mut ir::Component, From 975342972e846a374503ef783d8b73eaffeba185 Mon Sep 17 00:00:00 2001 From: Pai Li Date: Sun, 30 Apr 2023 23:31:59 -0400 Subject: [PATCH 03/14] modified compile-static to compile whiles with static bodies --- calyx-opt/src/passes/compile_static.rs | 114 ++++++++++++++++-- tests/correctness/static-control/while.expect | 8 ++ tests/correctness/static-control/while.futil | 29 +++++ .../static-control/while.futil.data | 12 ++ .../rewrite-static-while.expect | 36 ++++++ .../compile-static/rewrite-static-while.futil | 30 +++++ 6 files changed, 219 insertions(+), 10 deletions(-) create mode 100644 tests/correctness/static-control/while.expect create mode 100644 tests/correctness/static-control/while.futil create mode 100644 tests/correctness/static-control/while.futil.data create mode 100644 tests/passes/compile-static/rewrite-static-while.expect create mode 100644 tests/passes/compile-static/rewrite-static-while.futil diff --git a/calyx-opt/src/passes/compile_static.rs b/calyx-opt/src/passes/compile_static.rs index 5de4700664..1b764c9fe0 100644 --- a/calyx-opt/src/passes/compile_static.rs +++ b/calyx-opt/src/passes/compile_static.rs @@ -2,7 +2,7 @@ use super::math_utilities::get_bit_width_from; use crate::traversal::{Action, Named, VisResult, Visitor}; use calyx_ir as ir; use calyx_ir::{guard, structure, GetAttributes}; -use ir::{build_assignments, Nothing, StaticTiming}; +use ir::{build_assignments, Nothing, StaticTiming, RRC}; use itertools::Itertools; use std::collections::HashMap; use std::ops::Not; @@ -239,6 +239,81 @@ impl CompileStatic { early_reset_group.borrow().attributes.clone(); g } + + fn get_reset_group_name(&self, sc: &mut ir::StaticControl) -> &ir::Id { + // assume that there are only static enables left. + // if there are any other type of static control, then error out. + let ir::StaticControl::Enable(s) = sc else { + unreachable!("Non-Enable Static Control should have been compiled away. Run {} to do this", crate::passes::StaticInliner::name()); + }; + + let sgroup = s.group.borrow_mut(); + let sgroup_name = sgroup.name(); + // get the "early reset group". It should exist, since we made an + // early_reset group for every static group in the component + let early_reset_name = + self.reset_early_map.get(&sgroup_name).unwrap_or_else(|| { + unreachable!( + "group {} not in self.reset_early_map", + sgroup_name + ) + }); + + early_reset_name + } + + fn build_wrapper_group_while( + &self, + fsm_name: &ir::Id, + fsm_width: u64, + group_name: &ir::Id, + port: RRC, + builder: &mut ir::Builder, + ) -> RRC { + let reset_early_group = builder + .component + .find_group(*group_name) + .unwrap_or_else(|| { + unreachable!( + "called build_wrapper_group with {}, which is not a group", + group_name + ) + }); + let early_reset_fsm = + builder.component.find_cell(*fsm_name).unwrap_or_else(|| { + unreachable!( + "called build_wrapper_group with {}, which is not an fsm", + fsm_name + ) + }); + + let wrapper_group = + builder.add_group(format!("while_wrapper_{}", group_name)); + + structure!( + builder; + let one = constant(1, 1); + let time_0 = constant(0, fsm_width); + ); + + let port_parent = port.borrow().cell_parent(); + let port_name = port.borrow().name; + let done_guard = (!guard!(port_parent[port_name])) + & guard!(early_reset_fsm["out"]).eq(guard!(time_0["out"])); + + let assignments = build_assignments!( + builder; + reset_early_group["go"] = ? one["out"]; + // cond_reg["in"] = time_guard_0 ? port_parent[port_name]; + // cond_reg["write_en"] = time_guard_0 ? one["out"]; + // cond_wire["in"] = time_guard_0 ? port_parent[port_name]; + // cond_wire["in"] = not_0 ? cond_reg["out"]; + wrapper_group["done"] = done_guard ? one["out"]; + ); + + wrapper_group.borrow_mut().assignments.extend(assignments); + wrapper_group + } } impl Visitor for CompileStatic { @@ -346,17 +421,36 @@ impl Visitor for CompileStatic { Ok(Action::Change(Box::new(e))) } - fn finish_while( - &mut self, - s: &mut ir::While, - _comp: &mut ir::Component, - _sigs: &ir::LibrarySignatures, - _comps: &[ir::Component], - ) -> VisResult { - if (matches!(*(s.body), ir::Control::Static(_))) && s.cond.is_none() { + fn start_while( + &mut self, + s: &mut ir::While, + comp: &mut ir::Component, + sigs: &ir::LibrarySignatures, + _comps: &[ir::Component], + ) -> VisResult { + if s.cond.is_none() { + match &mut *(s.body) { + ir::Control::Static(sc) => { + let mut builder = ir::Builder::new(comp, sigs); + let reset_group_name = self.get_reset_group_name(sc); + // get fsm for reset_group + let (fsm, fsm_width) = self.fsm_info_map.get(reset_group_name).unwrap_or_else(|| unreachable!("group {} has no correspondoing fsm in self.fsm_map", reset_group_name)); + let wrapper_group = self.build_wrapper_group_while( + fsm, + *fsm_width, + reset_group_name, + Rc::clone(&s.port), + &mut builder, + ); + let c = ir::Control::enable(wrapper_group); + return Ok(Action::change(c)); + } + _ => (), } - Ok(Action::Continue) + } + + Ok(Action::Continue) } fn finish( diff --git a/tests/correctness/static-control/while.expect b/tests/correctness/static-control/while.expect new file mode 100644 index 0000000000..a1a52cbe0a --- /dev/null +++ b/tests/correctness/static-control/while.expect @@ -0,0 +1,8 @@ +{ + "cycles": 6, + "memories": { + "p": [ + 6 + ] + } +} diff --git a/tests/correctness/static-control/while.futil b/tests/correctness/static-control/while.futil new file mode 100644 index 0000000000..fb50d385e1 --- /dev/null +++ b/tests/correctness/static-control/while.futil @@ -0,0 +1,29 @@ +import "primitives/core.futil"; +import "primitives/pipelined.futil"; + +component main () -> () { + cells { + @external p = std_mem_d1(3,1,1); + incr = std_add(3); + l = std_lt(3); + } + + wires { + static group A<1> { + incr.left = p.read_data; + incr.right = 3'd1; + p.write_data = incr.out; + p.write_en = %0 ? 1'd1; + p.addr0 = 1'd0; + } + + l.left = p.read_data; + l.right = 3'd6; + } + + control { + while l.out { + A; + } + } +} \ No newline at end of file diff --git a/tests/correctness/static-control/while.futil.data b/tests/correctness/static-control/while.futil.data new file mode 100644 index 0000000000..7918761777 --- /dev/null +++ b/tests/correctness/static-control/while.futil.data @@ -0,0 +1,12 @@ +{ + "p": { + "data": [ + 0 + ], + "format": { + "numeric_type": "bitnum", + "is_signed": false, + "width": 32 + } + } +} \ No newline at end of file diff --git a/tests/passes/compile-static/rewrite-static-while.expect b/tests/passes/compile-static/rewrite-static-while.expect new file mode 100644 index 0000000000..c05ba4764d --- /dev/null +++ b/tests/passes/compile-static/rewrite-static-while.expect @@ -0,0 +1,36 @@ +import "primitives/core.futil"; +import "primitives/pipelined.futil"; +component main(@go go: 1, @clk clk: 1, @reset reset: 1) -> (@done done: 1) { + cells { + p = std_reg(3); + incr = std_add(3); + l = std_lt(3); + @generated fsm = std_reg(1); + @generated ud = undef(1); + @generated adder = std_add(1); + } + wires { + group early_reset_A { + incr.left = p.out; + incr.right = 3'd1; + p.in = incr.out; + p.write_en = fsm.out == 1'd0 ? 1'd1; + adder.left = fsm.out; + adder.right = 1'd1; + fsm.write_en = 1'd1; + fsm.in = fsm.out != 1'd0 ? adder.out; + fsm.in = fsm.out == 1'd0 ? 1'd0; + early_reset_A[done] = ud.out; + } + group while_wrapper_early_reset_A { + early_reset_A[go] = 1'd1; + while_wrapper_early_reset_A[done] = !l.out & fsm.out == 1'd0 ? 1'd1; + } + l.left = p.out; + l.right = 3'd6; + } + + control { + while_wrapper_early_reset_A; + } +} diff --git a/tests/passes/compile-static/rewrite-static-while.futil b/tests/passes/compile-static/rewrite-static-while.futil new file mode 100644 index 0000000000..310d6b829c --- /dev/null +++ b/tests/passes/compile-static/rewrite-static-while.futil @@ -0,0 +1,30 @@ +// -p well-formed -p compile-static -p dead-group-removal -p remove-ids + +import "primitives/core.futil"; +import "primitives/pipelined.futil"; + +component main () -> () { + cells { + p = std_reg(3); + incr = std_add(3); + l = std_lt(3); + } + + wires { + static group A<1> { + incr.left = p.out; + incr.right = 3'd1; + p.in = incr.out; + p.write_en = %0 ? 1'd1; + } + + l.left = p.out; + l.right = 3'd6; + } + + control { + while l.out { + A; + } + } +} \ No newline at end of file From cd26dde1dc2ef519cc5fe6fa1f37212a58ae561f Mon Sep 17 00:00:00 2001 From: Pai Li Date: Sun, 30 Apr 2023 23:51:50 -0400 Subject: [PATCH 04/14] added comments --- calyx-opt/src/passes/compile_static.rs | 35 ++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/calyx-opt/src/passes/compile_static.rs b/calyx-opt/src/passes/compile_static.rs index 1b764c9fe0..d6652ebdca 100644 --- a/calyx-opt/src/passes/compile_static.rs +++ b/calyx-opt/src/passes/compile_static.rs @@ -428,6 +428,41 @@ impl Visitor for CompileStatic { sigs: &ir::LibrarySignatures, _comps: &[ir::Component], ) -> VisResult { + // if while body is static, then we want to make sure that the while + // body does not take the extra cycle incurred by the done condition + // So we replace the while loop with `enable` of a wrapper group + // that sets the go signal of the static group in the while loop body high + // (all static control should be compiled into static groups by + // `static_inliner` now). The done signal of the wrapper group should be + // the condition that the fsm of the while body is %0 and the port signal + // is 1'd0. + // For example, we replace + // wires { + // static group A<1> { + // ... + // } + // ... + // } + + // control { + // while l.out { + // A; + // } + // } + // with + // wires { + // group early_reset_A { + // ... + // } + // + // group while_wrapper_early_reset_A { + // early_reset_A[go] = 1'd1; + // while_wrapper_early_reset_A[done] = !l.out & fsm.out == 1'd0 ? 1'd1; + // } + // } + // control { + // while_wrapper_early_reset_A; + // } if s.cond.is_none() { match &mut *(s.body) { ir::Control::Static(sc) => { From 13b486884f67b805cb411aa6a87289f56b11b600 Mon Sep 17 00:00:00 2001 From: Pai Li Date: Sun, 30 Apr 2023 23:58:26 -0400 Subject: [PATCH 05/14] fmt --- calyx-opt/src/passes/compile_static.rs | 45 ++++++++++++-------------- 1 file changed, 21 insertions(+), 24 deletions(-) diff --git a/calyx-opt/src/passes/compile_static.rs b/calyx-opt/src/passes/compile_static.rs index d6652ebdca..37366c24bd 100644 --- a/calyx-opt/src/passes/compile_static.rs +++ b/calyx-opt/src/passes/compile_static.rs @@ -429,59 +429,56 @@ impl Visitor for CompileStatic { _comps: &[ir::Component], ) -> VisResult { // if while body is static, then we want to make sure that the while - // body does not take the extra cycle incurred by the done condition + // body does not take the extra cycle incurred by the done condition // So we replace the while loop with `enable` of a wrapper group // that sets the go signal of the static group in the while loop body high - // (all static control should be compiled into static groups by + // (all static control should be compiled into static groups by // `static_inliner` now). The done signal of the wrapper group should be // the condition that the fsm of the while body is %0 and the port signal // is 1'd0. - // For example, we replace + // For example, we replace // wires { // static group A<1> { // ... // } // ... // } - + // control { // while l.out { // A; // } // } - // with + // with // wires { // group early_reset_A { - // ... + // ... // } // // group while_wrapper_early_reset_A { // early_reset_A[go] = 1'd1; // while_wrapper_early_reset_A[done] = !l.out & fsm.out == 1'd0 ? 1'd1; - // } + // } // } // control { // while_wrapper_early_reset_A; // } if s.cond.is_none() { - match &mut *(s.body) { - ir::Control::Static(sc) => { - let mut builder = ir::Builder::new(comp, sigs); - let reset_group_name = self.get_reset_group_name(sc); + if let ir::Control::Static(sc) = &mut *(s.body) { + let mut builder = ir::Builder::new(comp, sigs); + let reset_group_name = self.get_reset_group_name(sc); - // get fsm for reset_group - let (fsm, fsm_width) = self.fsm_info_map.get(reset_group_name).unwrap_or_else(|| unreachable!("group {} has no correspondoing fsm in self.fsm_map", reset_group_name)); - let wrapper_group = self.build_wrapper_group_while( - fsm, - *fsm_width, - reset_group_name, - Rc::clone(&s.port), - &mut builder, - ); - let c = ir::Control::enable(wrapper_group); - return Ok(Action::change(c)); - } - _ => (), + // get fsm for reset_group + let (fsm, fsm_width) = self.fsm_info_map.get(reset_group_name).unwrap_or_else(|| unreachable!("group {} has no correspondoing fsm in self.fsm_map", reset_group_name)); + let wrapper_group = self.build_wrapper_group_while( + fsm, + *fsm_width, + reset_group_name, + Rc::clone(&s.port), + &mut builder, + ); + let c = ir::Control::enable(wrapper_group); + return Ok(Action::change(c)); } } From 13d677f778718c4e2330a460e8ed09f6b7a441e9 Mon Sep 17 00:00:00 2001 From: Pai Li Date: Tue, 2 May 2023 15:41:58 -0400 Subject: [PATCH 06/14] counterexamples --- .../static-control/while-counterexample.futil | 43 ++++++++++++++++ .../while-counterexample.futil.data | 12 +++++ .../compile-static/counterexample.expect | 50 +++++++++++++++++++ .../compile-static/counterexample.futil | 44 ++++++++++++++++ 4 files changed, 149 insertions(+) create mode 100644 tests/correctness/static-control/while-counterexample.futil create mode 100644 tests/correctness/static-control/while-counterexample.futil.data create mode 100644 tests/passes/compile-static/counterexample.expect create mode 100644 tests/passes/compile-static/counterexample.futil diff --git a/tests/correctness/static-control/while-counterexample.futil b/tests/correctness/static-control/while-counterexample.futil new file mode 100644 index 0000000000..e2a593a33a --- /dev/null +++ b/tests/correctness/static-control/while-counterexample.futil @@ -0,0 +1,43 @@ +import "primitives/core.futil"; +import "primitives/pipelined.futil"; + +component main () -> () { + cells { + p = std_reg(5); + w = std_wire(5); + incr = std_add(5); + l = std_lt(5); + @external mem = std_mem_d1(5, 1, 1); + } + + wires { + static group A<1> { + incr.left = p.out; + incr.right = 5'd1; + p.in = incr.out; + p.write_en = %0 ? 1'd1; + w.in = %0 ? incr.out; + } + + static group B<1> { + incr.left = p.out; + incr.right = mem.read_data; + mem.write_data = incr.out; + mem.write_en = %0 ? 1'd1; + mem.addr0 = 1'd0; + w.in = p.out; + } + + l.left = w.out; + l.right = 5'd6; + + } + + control { + while l.out { + static seq { + A; B; + } + } + } +} \ No newline at end of file diff --git a/tests/correctness/static-control/while-counterexample.futil.data b/tests/correctness/static-control/while-counterexample.futil.data new file mode 100644 index 0000000000..f79d681bc3 --- /dev/null +++ b/tests/correctness/static-control/while-counterexample.futil.data @@ -0,0 +1,12 @@ +{ + "mem": { + "data": [ + 0 + ], + "format": { + "numeric_type": "bitnum", + "is_signed": false, + "width": 5 + } + } +} \ No newline at end of file diff --git a/tests/passes/compile-static/counterexample.expect b/tests/passes/compile-static/counterexample.expect new file mode 100644 index 0000000000..af15d0c536 --- /dev/null +++ b/tests/passes/compile-static/counterexample.expect @@ -0,0 +1,50 @@ +import "primitives/core.futil"; +import "primitives/pipelined.futil"; +component main(@go go: 1, @clk clk: 1, @reset reset: 1) -> (@done done: 1) { + cells { + p = std_reg(5); + w = std_wire(5); + incr = std_add(5); + l = std_lt(5); + @external mem = std_mem_d1(5, 1, 1); + @generated fsm = std_reg(1); + @generated ud = undef(1); + @generated adder = std_add(1); + @generated fsm0 = std_reg(1); + @generated ud0 = undef(1); + @generated adder0 = std_add(1); + @generated fsm1 = std_reg(2); + @generated ud1 = undef(1); + @generated adder1 = std_add(2); + } + wires { + group early_reset_static_seq { + incr.left = fsm1.out == 2'd0 ? p.out; + incr.right = fsm1.out == 2'd0 ? 5'd1; + p.in = fsm1.out == 2'd0 ? incr.out; + p.write_en = fsm1.out == 2'd0 ? 1'd1; + w.in = fsm1.out == 2'd0 ? incr.out; + incr.left = fsm1.out == 2'd1 ? p.out; + incr.right = fsm1.out == 2'd1 ? mem.read_data; + mem.write_data = fsm1.out == 2'd1 ? incr.out; + mem.write_en = fsm1.out == 2'd1 ? 1'd1; + mem.addr0 = fsm1.out == 2'd1 ? 1'd0; + adder1.left = fsm1.out; + adder1.right = 2'd1; + fsm1.write_en = 1'd1; + fsm1.in = fsm1.out != 2'd1 ? adder1.out; + fsm1.in = fsm1.out == 2'd1 ? 2'd0; + early_reset_static_seq[done] = ud1.out; + } + group while_wrapper_early_reset_static_seq { + early_reset_static_seq[go] = 1'd1; + while_wrapper_early_reset_static_seq[done] = !l.out & fsm1.out == 2'd0 ? 1'd1; + } + l.left = w.out; + l.right = 5'd6; + } + + control { + while_wrapper_early_reset_static_seq; + } +} diff --git a/tests/passes/compile-static/counterexample.futil b/tests/passes/compile-static/counterexample.futil new file mode 100644 index 0000000000..a2577f401f --- /dev/null +++ b/tests/passes/compile-static/counterexample.futil @@ -0,0 +1,44 @@ +// -p well-formed -p static-inline -p compile-static -p dead-group-removal -p remove-ids + +import "primitives/core.futil"; +import "primitives/pipelined.futil"; + +component main () -> () { + cells { + p = std_reg(5); + w = std_wire(5); + incr = std_add(5); + l = std_lt(5); + @external mem = std_mem_d1(5, 1, 1); + } + + wires { + static group A<1> { + incr.left = p.out; + incr.right = 5'd1; + p.in = incr.out; + p.write_en = %0 ? 1'd1; + w.in = %0 ? incr.out; + } + + static group B<1> { + incr.left = p.out; + incr.right = mem.read_data; + mem.write_data = incr.out; + mem.write_en = %0 ? 1'd1; + mem.addr0 = 1'd0; + } + + l.left = w.out; + l.right = 5'd6; + + } + + control { + while l.out { + static seq { + A; B; + } + } + } +} \ No newline at end of file From e93c6a1564b4ad504ed293c162dd948cf91797d3 Mon Sep 17 00:00:00 2001 From: Pai Li Date: Wed, 3 May 2023 20:42:10 -0400 Subject: [PATCH 07/14] another counterexample --- .../static-control/counterexample2.futil | 43 +++++++++++++++++++ .../static-control/counterexample2.futil.data | 12 ++++++ 2 files changed, 55 insertions(+) create mode 100644 tests/correctness/static-control/counterexample2.futil create mode 100644 tests/correctness/static-control/counterexample2.futil.data diff --git a/tests/correctness/static-control/counterexample2.futil b/tests/correctness/static-control/counterexample2.futil new file mode 100644 index 0000000000..d0968ea6c1 --- /dev/null +++ b/tests/correctness/static-control/counterexample2.futil @@ -0,0 +1,43 @@ +import "primitives/core.futil"; +import "primitives/pipelined.futil"; +component main () -> () { + cells { + p = std_reg(5); + w = std_wire(5); + A_exec_wire = std_wire(1); + incr = std_add(5); + l = std_lt(5); + @external mem = std_mem_d1(5, 1, 1); + } + wires { + static group A <1>{ + incr.left = p.out; + incr.right = 5'd1; + p.in = incr.out; + p.write_en = 1'd1; + // let w.out be the input to l.left + w.in = incr.out; + A_exec_wire.in = 1'd1; + } + static group B <1>{ + incr.left = p.out; + incr.right = mem.read_data; + mem.write_data = incr.out; + mem.write_en = 1'd1; + mem.addr0 = 1'd0; + } + w.in = !A_exec_wire.out ? p.out; + l.left = w.out; + l.right = 5'd6; + } + control { + while l.out { + static seq { + A; B; + } + } + } +} + + + diff --git a/tests/correctness/static-control/counterexample2.futil.data b/tests/correctness/static-control/counterexample2.futil.data new file mode 100644 index 0000000000..f1f004616e --- /dev/null +++ b/tests/correctness/static-control/counterexample2.futil.data @@ -0,0 +1,12 @@ +{ + "mem": { + "data": [ + 0 + ], + "format": { + "is_signed": false, + "numeric_type": "bitnum", + "width": 5 + } + } +} \ No newline at end of file From 8b66da827af95febe0dc03efe2494f14c1978629 Mon Sep 17 00:00:00 2001 From: Pai Li Date: Mon, 15 May 2023 12:08:34 -0400 Subject: [PATCH 08/14] addressed comments and added test case with nested loops --- calyx-opt/src/passes/compile_static.rs | 95 +++++++++++-------- .../static-control/nested-static-while.expect | 9 ++ .../static-control/nested-static-while.futil | 57 +++++++++++ .../nested-static-while.futil.data | 12 +++ .../rewrite-static-while-nested.expect | 62 ++++++++++++ .../rewrite-static-while-nested.futil | 59 ++++++++++++ 6 files changed, 252 insertions(+), 42 deletions(-) create mode 100644 tests/correctness/static-control/nested-static-while.expect create mode 100644 tests/correctness/static-control/nested-static-while.futil create mode 100644 tests/correctness/static-control/nested-static-while.futil.data create mode 100644 tests/passes/compile-static/rewrite-static-while-nested.expect create mode 100644 tests/passes/compile-static/rewrite-static-while-nested.futil diff --git a/calyx-opt/src/passes/compile_static.rs b/calyx-opt/src/passes/compile_static.rs index 37366c24bd..25342b40a0 100644 --- a/calyx-opt/src/passes/compile_static.rs +++ b/calyx-opt/src/passes/compile_static.rs @@ -7,6 +7,7 @@ use itertools::Itertools; use std::collections::HashMap; use std::ops::Not; use std::rc::Rc; +use calyx_utils::Error; #[derive(Default)] /// Compiles Static Islands @@ -262,6 +263,14 @@ impl CompileStatic { early_reset_name } + /// compile `while` whose body is `static` control such that at the end of each + /// iteration, the checking of condition does not incur an extra cycle of + /// latency. + /// We do this by wrapping the early reset group of the body with + /// another wrapper group, which sets the go signal of the early reset group + /// high, and is done when at the 0th cycle of each iteration, the condtion + /// port is done. + /// Note: this only works if the port for the while condition is `@stable`. fn build_wrapper_group_while( &self, fsm_name: &ir::Id, @@ -303,11 +312,9 @@ impl CompileStatic { let assignments = build_assignments!( builder; - reset_early_group["go"] = ? one["out"]; - // cond_reg["in"] = time_guard_0 ? port_parent[port_name]; - // cond_reg["write_en"] = time_guard_0 ? one["out"]; - // cond_wire["in"] = time_guard_0 ? port_parent[port_name]; - // cond_wire["in"] = not_0 ? cond_reg["out"]; + // reset_early_group[go] = 1'd1; + // wrapper_group[done] = !port ? 1'd1; + reset_early_group["go"] = ? one["out"]; wrapper_group["done"] = done_guard ? one["out"]; ); @@ -381,7 +388,7 @@ impl Visitor for CompileStatic { // assume that there are only static enables left. // if there are any other type of static control, then error out. let ir::StaticControl::Enable(s) = sc else { - unreachable!("Non-Enable Static Control should have been compiled away. Run {} to do this", crate::passes::StaticInliner::name()); + return Err(Error::malformed_control(format!("Non-Enable Static Control should have been compiled away. Run {} to do this", crate::passes::StaticInliner::name()))); }; let sgroup = s.group.borrow_mut(); @@ -391,7 +398,7 @@ impl Visitor for CompileStatic { let early_reset_name = self.reset_early_map.get(&sgroup_name).unwrap_or_else(|| { unreachable!( - "group {} not in self.reset_early_map", + "group {} early reset wrapper has not been created", sgroup_name ) }); @@ -421,6 +428,45 @@ impl Visitor for CompileStatic { Ok(Action::Change(Box::new(e))) } +/// if while body is static, then we want to make sure that the while +/// body does not take the extra cycle incurred by the done condition +/// So we replace the while loop with `enable` of a wrapper group +/// that sets the go signal of the static group in the while loop body high +/// (all static control should be compiled into static groups by +/// `static_inliner` now). The done signal of the wrapper group should be +/// the condition that the fsm of the while body is %0 and the port signal +/// is 1'd0. +/// For example, we replace +/// ``` +/// wires { +/// static group A<1> { +/// ... +/// } +/// ... +/// } + +/// control { +/// while l.out { +/// A; +/// } +/// } +/// ``` +/// with +/// ``` +/// wires { +/// group early_reset_A { +/// ... +/// } +/// +/// group while_wrapper_early_reset_A { +/// early_reset_A[go] = 1'd1; +/// while_wrapper_early_reset_A[done] = !l.out & fsm.out == 1'd0 ? 1'd1; +/// } +/// } +/// control { +/// while_wrapper_early_reset_A; +/// } +/// ``` fn start_while( &mut self, s: &mut ir::While, @@ -428,41 +474,6 @@ impl Visitor for CompileStatic { sigs: &ir::LibrarySignatures, _comps: &[ir::Component], ) -> VisResult { - // if while body is static, then we want to make sure that the while - // body does not take the extra cycle incurred by the done condition - // So we replace the while loop with `enable` of a wrapper group - // that sets the go signal of the static group in the while loop body high - // (all static control should be compiled into static groups by - // `static_inliner` now). The done signal of the wrapper group should be - // the condition that the fsm of the while body is %0 and the port signal - // is 1'd0. - // For example, we replace - // wires { - // static group A<1> { - // ... - // } - // ... - // } - - // control { - // while l.out { - // A; - // } - // } - // with - // wires { - // group early_reset_A { - // ... - // } - // - // group while_wrapper_early_reset_A { - // early_reset_A[go] = 1'd1; - // while_wrapper_early_reset_A[done] = !l.out & fsm.out == 1'd0 ? 1'd1; - // } - // } - // control { - // while_wrapper_early_reset_A; - // } if s.cond.is_none() { if let ir::Control::Static(sc) = &mut *(s.body) { let mut builder = ir::Builder::new(comp, sigs); diff --git a/tests/correctness/static-control/nested-static-while.expect b/tests/correctness/static-control/nested-static-while.expect new file mode 100644 index 0000000000..d7175a5bef --- /dev/null +++ b/tests/correctness/static-control/nested-static-while.expect @@ -0,0 +1,9 @@ +{ + "cycles": 41, + "memories": { + "p": [ + 6 + ] + } +} + diff --git a/tests/correctness/static-control/nested-static-while.futil b/tests/correctness/static-control/nested-static-while.futil new file mode 100644 index 0000000000..ac9590dae4 --- /dev/null +++ b/tests/correctness/static-control/nested-static-while.futil @@ -0,0 +1,57 @@ +import "primitives/core.futil"; +import "primitives/pipelined.futil"; + +component main () -> () { + cells { + @external p = std_mem_d1(3,1,1); + incr = std_add(3); + l = std_lt(3); + r = std_reg(3); + l2 = std_lt(3); + } + + wires { + static group A<1> { + incr.left = p.read_data; + incr.right = 3'd1; + p.write_data = incr.out; + p.write_en = %0 ? 1'd1; + p.addr0 = 1'd0; + } + + group B { + p.write_data = 3'd0; + p.write_en = 1'd1; + p.addr0 = 1'd0; + B[done] = p.done; + } + + group C { + r.in = incr.out; + incr.left = r.out; + incr.right = 3'd1; + r.write_en = 1'd1; + C[done] = r.done; + } + + comb group comp { + l2.left = r.out; + l2.right = 3'd3; + } + + l.left = p.read_data; + l.right = 3'd6; + } + + control { + while l2.out with comp { + seq { + B; + while l.out { + A; + } + C; + } + } + } +} \ No newline at end of file diff --git a/tests/correctness/static-control/nested-static-while.futil.data b/tests/correctness/static-control/nested-static-while.futil.data new file mode 100644 index 0000000000..7918761777 --- /dev/null +++ b/tests/correctness/static-control/nested-static-while.futil.data @@ -0,0 +1,12 @@ +{ + "p": { + "data": [ + 0 + ], + "format": { + "numeric_type": "bitnum", + "is_signed": false, + "width": 32 + } + } +} \ No newline at end of file diff --git a/tests/passes/compile-static/rewrite-static-while-nested.expect b/tests/passes/compile-static/rewrite-static-while-nested.expect new file mode 100644 index 0000000000..3343a059e3 --- /dev/null +++ b/tests/passes/compile-static/rewrite-static-while-nested.expect @@ -0,0 +1,62 @@ +import "primitives/core.futil"; +import "primitives/pipelined.futil"; +component main(@go go: 1, @clk clk: 1, @reset reset: 1) -> (@done done: 1) { + cells { + @external p = std_mem_d1(3, 1, 1); + incr = std_add(3); + l = std_lt(3); + r = std_reg(3); + l2 = std_lt(3); + @generated fsm = std_reg(1); + @generated ud = undef(1); + @generated adder = std_add(1); + } + wires { + group B { + p.write_data = 3'd0; + p.write_en = 1'd1; + p.addr0 = 1'd0; + B[done] = p.done; + } + group C { + r.in = incr.out; + incr.left = r.out; + incr.right = 3'd1; + r.write_en = 1'd1; + C[done] = r.done; + } + group early_reset_A { + incr.left = p.read_data; + incr.right = 3'd1; + p.write_data = incr.out; + p.write_en = fsm.out == 1'd0 ? 1'd1; + p.addr0 = 1'd0; + adder.left = fsm.out; + adder.right = 1'd1; + fsm.write_en = 1'd1; + fsm.in = fsm.out != 1'd0 ? adder.out; + fsm.in = fsm.out == 1'd0 ? 1'd0; + early_reset_A[done] = ud.out; + } + group while_wrapper_early_reset_A { + early_reset_A[go] = 1'd1; + while_wrapper_early_reset_A[done] = !l.out & fsm.out == 1'd0 ? 1'd1; + } + comb group comp { + l2.left = r.out; + l2.right = 3'd3; + } + l.left = p.read_data; + l.right = 3'd6; + } + + control { + while l2.out with comp { + seq { + B; + while_wrapper_early_reset_A; + C; + } + } + } +} diff --git a/tests/passes/compile-static/rewrite-static-while-nested.futil b/tests/passes/compile-static/rewrite-static-while-nested.futil new file mode 100644 index 0000000000..cb10562a20 --- /dev/null +++ b/tests/passes/compile-static/rewrite-static-while-nested.futil @@ -0,0 +1,59 @@ +// -p well-formed -p compile-static -p dead-group-removal -p remove-ids + +import "primitives/core.futil"; +import "primitives/pipelined.futil"; + +component main () -> () { + cells { + @external p = std_mem_d1(3,1,1); + incr = std_add(3); + l = std_lt(3); + r = std_reg(3); + l2 = std_lt(3); + } + + wires { + static group A<1> { + incr.left = p.read_data; + incr.right = 3'd1; + p.write_data = incr.out; + p.write_en = %0 ? 1'd1; + p.addr0 = 1'd0; + } + + group B { + p.write_data = 3'd0; + p.write_en = 1'd1; + p.addr0 = 1'd0; + B[done] = p.done; + } + + group C { + r.in = incr.out; + incr.left = r.out; + incr.right = 3'd1; + r.write_en = 1'd1; + C[done] = r.done; + } + + comb group comp { + l2.left = r.out; + l2.right = 3'd3; + } + + l.left = p.read_data; + l.right = 3'd6; + } + + control { + while l2.out with comp { + seq { + B; + while l.out { + A; + } + C; + } + } + } +} \ No newline at end of file From 721aa1376f10702357837fb2c7577e0dc731ef4f Mon Sep 17 00:00:00 2001 From: Pai Li Date: Mon, 15 May 2023 12:09:32 -0400 Subject: [PATCH 09/14] fmt --- calyx-opt/src/passes/compile_static.rs | 88 +++++++++++++------------- 1 file changed, 44 insertions(+), 44 deletions(-) diff --git a/calyx-opt/src/passes/compile_static.rs b/calyx-opt/src/passes/compile_static.rs index 25342b40a0..0cd8735308 100644 --- a/calyx-opt/src/passes/compile_static.rs +++ b/calyx-opt/src/passes/compile_static.rs @@ -2,12 +2,12 @@ use super::math_utilities::get_bit_width_from; use crate::traversal::{Action, Named, VisResult, Visitor}; use calyx_ir as ir; use calyx_ir::{guard, structure, GetAttributes}; +use calyx_utils::Error; use ir::{build_assignments, Nothing, StaticTiming, RRC}; use itertools::Itertools; use std::collections::HashMap; use std::ops::Not; use std::rc::Rc; -use calyx_utils::Error; #[derive(Default)] /// Compiles Static Islands @@ -264,11 +264,11 @@ impl CompileStatic { } /// compile `while` whose body is `static` control such that at the end of each - /// iteration, the checking of condition does not incur an extra cycle of - /// latency. - /// We do this by wrapping the early reset group of the body with + /// iteration, the checking of condition does not incur an extra cycle of + /// latency. + /// We do this by wrapping the early reset group of the body with /// another wrapper group, which sets the go signal of the early reset group - /// high, and is done when at the 0th cycle of each iteration, the condtion + /// high, and is done when at the 0th cycle of each iteration, the condtion /// port is done. /// Note: this only works if the port for the while condition is `@stable`. fn build_wrapper_group_while( @@ -314,7 +314,7 @@ impl CompileStatic { builder; // reset_early_group[go] = 1'd1; // wrapper_group[done] = !port ? 1'd1; - reset_early_group["go"] = ? one["out"]; + reset_early_group["go"] = ? one["out"]; wrapper_group["done"] = done_guard ? one["out"]; ); @@ -428,45 +428,45 @@ impl Visitor for CompileStatic { Ok(Action::Change(Box::new(e))) } -/// if while body is static, then we want to make sure that the while -/// body does not take the extra cycle incurred by the done condition -/// So we replace the while loop with `enable` of a wrapper group -/// that sets the go signal of the static group in the while loop body high -/// (all static control should be compiled into static groups by -/// `static_inliner` now). The done signal of the wrapper group should be -/// the condition that the fsm of the while body is %0 and the port signal -/// is 1'd0. -/// For example, we replace -/// ``` -/// wires { -/// static group A<1> { -/// ... -/// } -/// ... -/// } + /// if while body is static, then we want to make sure that the while + /// body does not take the extra cycle incurred by the done condition + /// So we replace the while loop with `enable` of a wrapper group + /// that sets the go signal of the static group in the while loop body high + /// (all static control should be compiled into static groups by + /// `static_inliner` now). The done signal of the wrapper group should be + /// the condition that the fsm of the while body is %0 and the port signal + /// is 1'd0. + /// For example, we replace + /// ``` + /// wires { + /// static group A<1> { + /// ... + /// } + /// ... + /// } -/// control { -/// while l.out { -/// A; -/// } -/// } -/// ``` -/// with -/// ``` -/// wires { -/// group early_reset_A { -/// ... -/// } -/// -/// group while_wrapper_early_reset_A { -/// early_reset_A[go] = 1'd1; -/// while_wrapper_early_reset_A[done] = !l.out & fsm.out == 1'd0 ? 1'd1; -/// } -/// } -/// control { -/// while_wrapper_early_reset_A; -/// } -/// ``` + /// control { + /// while l.out { + /// A; + /// } + /// } + /// ``` + /// with + /// ``` + /// wires { + /// group early_reset_A { + /// ... + /// } + /// + /// group while_wrapper_early_reset_A { + /// early_reset_A[go] = 1'd1; + /// while_wrapper_early_reset_A[done] = !l.out & fsm.out == 1'd0 ? 1'd1; + /// } + /// } + /// control { + /// while_wrapper_early_reset_A; + /// } + /// ``` fn start_while( &mut self, s: &mut ir::While, From 3164193a835ddc366ae75ce21799a2b8f924c1d8 Mon Sep 17 00:00:00 2001 From: Pai Li Date: Mon, 15 May 2023 12:33:06 -0400 Subject: [PATCH 10/14] fixed test cases --- examples/tutorial/language-tutorial-mem.expect | 2 +- tests/correctness/static-control/nested-static-while.expect | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/examples/tutorial/language-tutorial-mem.expect b/examples/tutorial/language-tutorial-mem.expect index e9e1a28af2..d87cad1b8e 100644 --- a/examples/tutorial/language-tutorial-mem.expect +++ b/examples/tutorial/language-tutorial-mem.expect @@ -1,5 +1,5 @@ { - "cycles": 0, + "cycles": 1, "memories": { "mem": [ 42 diff --git a/tests/correctness/static-control/nested-static-while.expect b/tests/correctness/static-control/nested-static-while.expect index d7175a5bef..06fb227263 100644 --- a/tests/correctness/static-control/nested-static-while.expect +++ b/tests/correctness/static-control/nested-static-while.expect @@ -6,4 +6,3 @@ ] } } - From 7656ac224cd0be92ba310662de4c3e198c051966 Mon Sep 17 00:00:00 2001 From: Pai Li Date: Mon, 15 May 2023 15:32:05 -0400 Subject: [PATCH 11/14] modified test cases --- tests/correctness/static-control/while.expect | 23 ++++-- tests/correctness/static-control/while.futil | 29 ++++++-- .../compile-static/counterexample.expect | 56 ++------------ .../compile-static/counterexample.futil | 4 +- .../rewrite-static-while-nested.expect | 74 ++++++++++++++----- .../rewrite-static-while-nested.futil | 21 ++++-- .../rewrite-static-while.expect | 74 ++++++++++++++----- .../compile-static/rewrite-static-while.futil | 25 +++++-- 8 files changed, 189 insertions(+), 117 deletions(-) diff --git a/tests/correctness/static-control/while.expect b/tests/correctness/static-control/while.expect index a1a52cbe0a..5207f2b5e0 100644 --- a/tests/correctness/static-control/while.expect +++ b/tests/correctness/static-control/while.expect @@ -1,8 +1,15 @@ -{ - "cycles": 6, - "memories": { - "p": [ - 6 - ] - } -} +---CODE--- +255 +---STDERR--- +[fud] WARNING: Unknown option `verilog.top_module' for stage `verilog' +[fud] WARNING: Unknown option `verilog.priority' for stage `verilog' +[fud] ERROR: `./target/debug/calyx -l /Users/paili/Desktop/capra/calyx-symbolic/calyx -b verilog --disable-init -p all -d tdst -d group2invoke' failed: +=====STDERR===== +Error: +28 | static<1> group B { + | ^^^^^^^^^^^^^^^^^^^ [Papercut] Required signal not driven inside the group. +When read the port `p.read_data', the ports [p.addr0] must be written to. +The primitive type `std_mem_d1' requires this invariant. + +=====STDOUT===== + diff --git a/tests/correctness/static-control/while.futil b/tests/correctness/static-control/while.futil index fb50d385e1..ae9e7fc018 100644 --- a/tests/correctness/static-control/while.futil +++ b/tests/correctness/static-control/while.futil @@ -6,24 +6,39 @@ component main () -> () { @external p = std_mem_d1(3,1,1); incr = std_add(3); l = std_lt(3); + r = std_reg(1); + s = std_reg(3); } wires { - static group A<1> { + static<1> group A { incr.left = p.read_data; incr.right = 3'd1; - p.write_data = incr.out; - p.write_en = %0 ? 1'd1; + s.in = incr.out; + s.write_en = %0 ? 1'd1; p.addr0 = 1'd0; } - l.left = p.read_data; - l.right = 3'd6; + static<1> group C { + p.write_data = s.out; + p.write_en = 1'd1; + p.addr0 = 1'd0; + } + + static<1> group B { + l.left = p.read_data; + l.right = 3'd6; + r.in = l.out; + r.write_en = 1'd1; + } } control { - while l.out { - A; + seq { + B; + while r.out { + static seq {A;C; B;} + } } } } \ No newline at end of file diff --git a/tests/passes/compile-static/counterexample.expect b/tests/passes/compile-static/counterexample.expect index af15d0c536..a46d4d4b53 100644 --- a/tests/passes/compile-static/counterexample.expect +++ b/tests/passes/compile-static/counterexample.expect @@ -1,50 +1,6 @@ -import "primitives/core.futil"; -import "primitives/pipelined.futil"; -component main(@go go: 1, @clk clk: 1, @reset reset: 1) -> (@done done: 1) { - cells { - p = std_reg(5); - w = std_wire(5); - incr = std_add(5); - l = std_lt(5); - @external mem = std_mem_d1(5, 1, 1); - @generated fsm = std_reg(1); - @generated ud = undef(1); - @generated adder = std_add(1); - @generated fsm0 = std_reg(1); - @generated ud0 = undef(1); - @generated adder0 = std_add(1); - @generated fsm1 = std_reg(2); - @generated ud1 = undef(1); - @generated adder1 = std_add(2); - } - wires { - group early_reset_static_seq { - incr.left = fsm1.out == 2'd0 ? p.out; - incr.right = fsm1.out == 2'd0 ? 5'd1; - p.in = fsm1.out == 2'd0 ? incr.out; - p.write_en = fsm1.out == 2'd0 ? 1'd1; - w.in = fsm1.out == 2'd0 ? incr.out; - incr.left = fsm1.out == 2'd1 ? p.out; - incr.right = fsm1.out == 2'd1 ? mem.read_data; - mem.write_data = fsm1.out == 2'd1 ? incr.out; - mem.write_en = fsm1.out == 2'd1 ? 1'd1; - mem.addr0 = fsm1.out == 2'd1 ? 1'd0; - adder1.left = fsm1.out; - adder1.right = 2'd1; - fsm1.write_en = 1'd1; - fsm1.in = fsm1.out != 2'd1 ? adder1.out; - fsm1.in = fsm1.out == 2'd1 ? 2'd0; - early_reset_static_seq[done] = ud1.out; - } - group while_wrapper_early_reset_static_seq { - early_reset_static_seq[go] = 1'd1; - while_wrapper_early_reset_static_seq[done] = !l.out & fsm1.out == 2'd0 ? 1'd1; - } - l.left = w.out; - l.right = 5'd6; - } - - control { - while_wrapper_early_reset_static_seq; - } -} +---CODE--- +1 +---STDERR--- +Error: Malformed Control: tests/passes/compile-static/counterexample.futil +38 | while l.out { + | ^^^^^^^^^^^^^ While loop has no comb group and its condition port l.out is unstable diff --git a/tests/passes/compile-static/counterexample.futil b/tests/passes/compile-static/counterexample.futil index a2577f401f..47312bccae 100644 --- a/tests/passes/compile-static/counterexample.futil +++ b/tests/passes/compile-static/counterexample.futil @@ -13,7 +13,7 @@ component main () -> () { } wires { - static group A<1> { + static<1> group A { incr.left = p.out; incr.right = 5'd1; p.in = incr.out; @@ -21,7 +21,7 @@ component main () -> () { w.in = %0 ? incr.out; } - static group B<1> { + static<1> group B { incr.left = p.out; incr.right = mem.read_data; mem.write_data = incr.out; diff --git a/tests/passes/compile-static/rewrite-static-while-nested.expect b/tests/passes/compile-static/rewrite-static-while-nested.expect index 3343a059e3..b9cbfd6c02 100644 --- a/tests/passes/compile-static/rewrite-static-while-nested.expect +++ b/tests/passes/compile-static/rewrite-static-while-nested.expect @@ -7,9 +7,18 @@ component main(@go go: 1, @clk clk: 1, @reset reset: 1) -> (@done done: 1) { l = std_lt(3); r = std_reg(3); l2 = std_lt(3); + r_cond = std_reg(1); @generated fsm = std_reg(1); @generated ud = undef(1); @generated adder = std_add(1); + @generated fsm0 = std_reg(1); + @generated ud0 = undef(1); + @generated adder0 = std_add(1); + @generated fsm1 = std_reg(2); + @generated ud1 = undef(1); + @generated adder1 = std_add(2); + @generated signal_reg = std_reg(1); + @generated signal_reg0 = std_reg(1); } wires { group B { @@ -25,36 +34,65 @@ component main(@go go: 1, @clk clk: 1, @reset reset: 1) -> (@done done: 1) { r.write_en = 1'd1; C[done] = r.done; } - group early_reset_A { - incr.left = p.read_data; - incr.right = 3'd1; - p.write_data = incr.out; - p.write_en = fsm.out == 1'd0 ? 1'd1; - p.addr0 = 1'd0; - adder.left = fsm.out; - adder.right = 1'd1; - fsm.write_en = 1'd1; - fsm.in = fsm.out != 1'd0 ? adder.out; - fsm.in = fsm.out == 1'd0 ? 1'd0; - early_reset_A[done] = ud.out; + group early_reset_A2 { + l.left = p.read_data; + l.right = 3'd6; + r_cond.in = l.out; + r_cond.write_en = 1'd1; + adder0.left = fsm0.out; + adder0.right = 1'd1; + fsm0.write_en = 1'd1; + fsm0.in = fsm0.out != 1'd0 ? adder0.out; + fsm0.in = fsm0.out == 1'd0 ? 1'd0; + early_reset_A2[done] = ud0.out; + } + group early_reset_static_seq { + incr.left = fsm1.out == 2'd0 ? p.read_data; + incr.right = fsm1.out == 2'd0 ? 3'd1; + p.write_data = fsm1.out == 2'd0 ? incr.out; + p.write_en = fsm1.out == 2'd0 ? 1'd1; + p.addr0 = fsm1.out == 2'd0 ? 1'd0; + l.left = fsm1.out == 2'd1 ? p.read_data; + l.right = fsm1.out == 2'd1 ? 3'd6; + r_cond.in = fsm1.out == 2'd1 ? l.out; + r_cond.write_en = fsm1.out == 2'd1 ? 1'd1; + adder1.left = fsm1.out; + adder1.right = 2'd1; + fsm1.write_en = 1'd1; + fsm1.in = fsm1.out != 2'd1 ? adder1.out; + fsm1.in = fsm1.out == 2'd1 ? 2'd0; + early_reset_static_seq[done] = ud1.out; + } + group wrapper_early_reset_A2 { + early_reset_A2[go] = 1'd1; + signal_reg.write_en = fsm0.out == 1'd0 & !signal_reg.out ? 1'd1; + signal_reg.in = fsm0.out == 1'd0 & !signal_reg.out ? 1'd1; + wrapper_early_reset_A2[done] = fsm0.out == 1'd0 & signal_reg.out ? 1'd1; } - group while_wrapper_early_reset_A { - early_reset_A[go] = 1'd1; - while_wrapper_early_reset_A[done] = !l.out & fsm.out == 1'd0 ? 1'd1; + group wrapper_early_reset_static_seq { + early_reset_static_seq[go] = 1'd1; + signal_reg0.write_en = fsm1.out == 2'd0 & !signal_reg0.out ? 1'd1; + signal_reg0.in = fsm1.out == 2'd0 & !signal_reg0.out ? 1'd1; + wrapper_early_reset_static_seq[done] = fsm1.out == 2'd0 & signal_reg0.out ? 1'd1; } comb group comp { l2.left = r.out; l2.right = 3'd3; } - l.left = p.read_data; - l.right = 3'd6; + signal_reg.write_en = fsm0.out == 1'd0 & signal_reg.out ? 1'd1; + signal_reg.in = fsm0.out == 1'd0 & signal_reg.out ? 1'd0; + signal_reg0.write_en = fsm1.out == 2'd0 & signal_reg0.out ? 1'd1; + signal_reg0.in = fsm1.out == 2'd0 & signal_reg0.out ? 1'd0; } control { while l2.out with comp { seq { B; - while_wrapper_early_reset_A; + wrapper_early_reset_A2; + while r_cond.out { + wrapper_early_reset_static_seq; + } C; } } diff --git a/tests/passes/compile-static/rewrite-static-while-nested.futil b/tests/passes/compile-static/rewrite-static-while-nested.futil index cb10562a20..08ffb8d364 100644 --- a/tests/passes/compile-static/rewrite-static-while-nested.futil +++ b/tests/passes/compile-static/rewrite-static-while-nested.futil @@ -1,4 +1,4 @@ -// -p well-formed -p compile-static -p dead-group-removal -p remove-ids +// -p well-formed -p static-inline -p compile-static -p dead-group-removal -p remove-ids import "primitives/core.futil"; import "primitives/pipelined.futil"; @@ -10,16 +10,24 @@ component main () -> () { l = std_lt(3); r = std_reg(3); l2 = std_lt(3); + r_cond = std_reg(1); } wires { - static group A<1> { + static<1> group A { incr.left = p.read_data; incr.right = 3'd1; p.write_data = incr.out; p.write_en = %0 ? 1'd1; p.addr0 = 1'd0; } + + static<1> group A2 { + l.left = p.read_data; + l.right = 3'd6; + r_cond.in = l.out; + r_cond.write_en = 1'd1; + } group B { p.write_data = 3'd0; @@ -40,17 +48,14 @@ component main () -> () { l2.left = r.out; l2.right = 3'd3; } - - l.left = p.read_data; - l.right = 3'd6; } control { while l2.out with comp { seq { - B; - while l.out { - A; + B; A2; + while r_cond.out { + static seq {A; A2;} } C; } diff --git a/tests/passes/compile-static/rewrite-static-while.expect b/tests/passes/compile-static/rewrite-static-while.expect index c05ba4764d..108d7a3adb 100644 --- a/tests/passes/compile-static/rewrite-static-while.expect +++ b/tests/passes/compile-static/rewrite-static-while.expect @@ -5,32 +5,72 @@ component main(@go go: 1, @clk clk: 1, @reset reset: 1) -> (@done done: 1) { p = std_reg(3); incr = std_add(3); l = std_lt(3); + r = std_reg(1); @generated fsm = std_reg(1); @generated ud = undef(1); @generated adder = std_add(1); + @generated fsm0 = std_reg(1); + @generated ud0 = undef(1); + @generated adder0 = std_add(1); + @generated fsm1 = std_reg(2); + @generated ud1 = undef(1); + @generated adder1 = std_add(2); + @generated signal_reg = std_reg(1); + @generated signal_reg0 = std_reg(1); } wires { - group early_reset_A { - incr.left = p.out; - incr.right = 3'd1; - p.in = incr.out; - p.write_en = fsm.out == 1'd0 ? 1'd1; - adder.left = fsm.out; - adder.right = 1'd1; - fsm.write_en = 1'd1; - fsm.in = fsm.out != 1'd0 ? adder.out; - fsm.in = fsm.out == 1'd0 ? 1'd0; - early_reset_A[done] = ud.out; + group early_reset_B { + l.left = p.out; + l.right = 3'd6; + r.in = l.out; + r.write_en = 1'd1; + adder0.left = fsm0.out; + adder0.right = 1'd1; + fsm0.write_en = 1'd1; + fsm0.in = fsm0.out != 1'd0 ? adder0.out; + fsm0.in = fsm0.out == 1'd0 ? 1'd0; + early_reset_B[done] = ud0.out; } - group while_wrapper_early_reset_A { - early_reset_A[go] = 1'd1; - while_wrapper_early_reset_A[done] = !l.out & fsm.out == 1'd0 ? 1'd1; + group early_reset_static_seq { + incr.left = fsm1.out == 2'd0 ? p.out; + incr.right = fsm1.out == 2'd0 ? 3'd1; + p.in = fsm1.out == 2'd0 ? incr.out; + p.write_en = fsm1.out == 2'd0 ? 1'd1; + l.left = fsm1.out == 2'd1 ? p.out; + l.right = fsm1.out == 2'd1 ? 3'd6; + r.in = fsm1.out == 2'd1 ? l.out; + r.write_en = fsm1.out == 2'd1 ? 1'd1; + adder1.left = fsm1.out; + adder1.right = 2'd1; + fsm1.write_en = 1'd1; + fsm1.in = fsm1.out != 2'd1 ? adder1.out; + fsm1.in = fsm1.out == 2'd1 ? 2'd0; + early_reset_static_seq[done] = ud1.out; } - l.left = p.out; - l.right = 3'd6; + group wrapper_early_reset_B { + early_reset_B[go] = 1'd1; + signal_reg.write_en = fsm0.out == 1'd0 & !signal_reg.out ? 1'd1; + signal_reg.in = fsm0.out == 1'd0 & !signal_reg.out ? 1'd1; + wrapper_early_reset_B[done] = fsm0.out == 1'd0 & signal_reg.out ? 1'd1; + } + group wrapper_early_reset_static_seq { + early_reset_static_seq[go] = 1'd1; + signal_reg0.write_en = fsm1.out == 2'd0 & !signal_reg0.out ? 1'd1; + signal_reg0.in = fsm1.out == 2'd0 & !signal_reg0.out ? 1'd1; + wrapper_early_reset_static_seq[done] = fsm1.out == 2'd0 & signal_reg0.out ? 1'd1; + } + signal_reg.write_en = fsm0.out == 1'd0 & signal_reg.out ? 1'd1; + signal_reg.in = fsm0.out == 1'd0 & signal_reg.out ? 1'd0; + signal_reg0.write_en = fsm1.out == 2'd0 & signal_reg0.out ? 1'd1; + signal_reg0.in = fsm1.out == 2'd0 & signal_reg0.out ? 1'd0; } control { - while_wrapper_early_reset_A; + seq { + wrapper_early_reset_B; + while r.out { + wrapper_early_reset_static_seq; + } + } } } diff --git a/tests/passes/compile-static/rewrite-static-while.futil b/tests/passes/compile-static/rewrite-static-while.futil index 310d6b829c..788c191cd9 100644 --- a/tests/passes/compile-static/rewrite-static-while.futil +++ b/tests/passes/compile-static/rewrite-static-while.futil @@ -1,4 +1,4 @@ -// -p well-formed -p compile-static -p dead-group-removal -p remove-ids +// -p well-formed -p static-inline -p compile-static -p dead-group-removal -p remove-ids import "primitives/core.futil"; import "primitives/pipelined.futil"; @@ -8,23 +8,34 @@ component main () -> () { p = std_reg(3); incr = std_add(3); l = std_lt(3); + r = std_reg(1); } wires { - static group A<1> { + static<1> group A { incr.left = p.out; incr.right = 3'd1; p.in = incr.out; p.write_en = %0 ? 1'd1; } - - l.left = p.out; - l.right = 3'd6; + static<1> group B { + l.left = p.out; + l.right = 3'd6; + r.in = l.out; + r.write_en = 1'd1; + } + } control { - while l.out { - A; + seq { + B; + while r.out { + static seq { + A; + B; + } + } } } } \ No newline at end of file From 04b996aa4d29589bd60ee78e2816e949622e32e1 Mon Sep 17 00:00:00 2001 From: Pai Li Date: Mon, 15 May 2023 15:59:04 -0400 Subject: [PATCH 12/14] test cases --- .../static-control/nested-static-while.expect | 2 +- .../static-control/nested-static-while.futil | 19 +++++--- .../static-control/while-counterexample.futil | 43 ------------------- .../while-counterexample.futil.data | 12 ------ tests/correctness/static-control/while.expect | 23 ++++------ tests/correctness/static-control/while.futil | 1 + .../rewrite-static-while-nested.expect | 2 + .../rewrite-static-while-nested.futil | 1 + 8 files changed, 27 insertions(+), 76 deletions(-) delete mode 100644 tests/correctness/static-control/while-counterexample.futil delete mode 100644 tests/correctness/static-control/while-counterexample.futil.data diff --git a/tests/correctness/static-control/nested-static-while.expect b/tests/correctness/static-control/nested-static-while.expect index 06fb227263..3b97cd1c75 100644 --- a/tests/correctness/static-control/nested-static-while.expect +++ b/tests/correctness/static-control/nested-static-while.expect @@ -1,5 +1,5 @@ { - "cycles": 41, + "cycles": 80, "memories": { "p": [ 6 diff --git a/tests/correctness/static-control/nested-static-while.futil b/tests/correctness/static-control/nested-static-while.futil index ac9590dae4..da64ac5565 100644 --- a/tests/correctness/static-control/nested-static-while.futil +++ b/tests/correctness/static-control/nested-static-while.futil @@ -8,16 +8,26 @@ component main () -> () { l = std_lt(3); r = std_reg(3); l2 = std_lt(3); + r_cond = std_reg(1); } wires { - static group A<1> { + static<1> group A { incr.left = p.read_data; incr.right = 3'd1; p.write_data = incr.out; p.write_en = %0 ? 1'd1; p.addr0 = 1'd0; } + + static<1> group A2 { + l.left = p.read_data; + l.right = 3'd6; + p.addr0 = 1'd0; + r_cond.in = l.out; + r_cond.write_en = 1'd1; + } + group B { p.write_data = 3'd0; @@ -39,16 +49,15 @@ component main () -> () { l2.right = 3'd3; } - l.left = p.read_data; - l.right = 3'd6; } control { while l2.out with comp { seq { B; - while l.out { - A; + A2; + while r_cond.out { + static seq { A; A2; } } C; } diff --git a/tests/correctness/static-control/while-counterexample.futil b/tests/correctness/static-control/while-counterexample.futil deleted file mode 100644 index e2a593a33a..0000000000 --- a/tests/correctness/static-control/while-counterexample.futil +++ /dev/null @@ -1,43 +0,0 @@ -import "primitives/core.futil"; -import "primitives/pipelined.futil"; - -component main () -> () { - cells { - p = std_reg(5); - w = std_wire(5); - incr = std_add(5); - l = std_lt(5); - @external mem = std_mem_d1(5, 1, 1); - } - - wires { - static group A<1> { - incr.left = p.out; - incr.right = 5'd1; - p.in = incr.out; - p.write_en = %0 ? 1'd1; - w.in = %0 ? incr.out; - } - - static group B<1> { - incr.left = p.out; - incr.right = mem.read_data; - mem.write_data = incr.out; - mem.write_en = %0 ? 1'd1; - mem.addr0 = 1'd0; - w.in = p.out; - } - - l.left = w.out; - l.right = 5'd6; - - } - - control { - while l.out { - static seq { - A; B; - } - } - } -} \ No newline at end of file diff --git a/tests/correctness/static-control/while-counterexample.futil.data b/tests/correctness/static-control/while-counterexample.futil.data deleted file mode 100644 index f79d681bc3..0000000000 --- a/tests/correctness/static-control/while-counterexample.futil.data +++ /dev/null @@ -1,12 +0,0 @@ -{ - "mem": { - "data": [ - 0 - ], - "format": { - "numeric_type": "bitnum", - "is_signed": false, - "width": 5 - } - } -} \ No newline at end of file diff --git a/tests/correctness/static-control/while.expect b/tests/correctness/static-control/while.expect index 5207f2b5e0..4541fc90b0 100644 --- a/tests/correctness/static-control/while.expect +++ b/tests/correctness/static-control/while.expect @@ -1,15 +1,8 @@ ----CODE--- -255 ----STDERR--- -[fud] WARNING: Unknown option `verilog.top_module' for stage `verilog' -[fud] WARNING: Unknown option `verilog.priority' for stage `verilog' -[fud] ERROR: `./target/debug/calyx -l /Users/paili/Desktop/capra/calyx-symbolic/calyx -b verilog --disable-init -p all -d tdst -d group2invoke' failed: -=====STDERR===== -Error: -28 | static<1> group B { - | ^^^^^^^^^^^^^^^^^^^ [Papercut] Required signal not driven inside the group. -When read the port `p.read_data', the ports [p.addr0] must be written to. -The primitive type `std_mem_d1' requires this invariant. - -=====STDOUT===== - +{ + "cycles": 26, + "memories": { + "p": [ + 6 + ] + } +} diff --git a/tests/correctness/static-control/while.futil b/tests/correctness/static-control/while.futil index ae9e7fc018..a48aa318a4 100644 --- a/tests/correctness/static-control/while.futil +++ b/tests/correctness/static-control/while.futil @@ -30,6 +30,7 @@ component main () -> () { l.right = 3'd6; r.in = l.out; r.write_en = 1'd1; + p.addr0 = 1'd0; } } diff --git a/tests/passes/compile-static/rewrite-static-while-nested.expect b/tests/passes/compile-static/rewrite-static-while-nested.expect index b9cbfd6c02..e3e9b4b719 100644 --- a/tests/passes/compile-static/rewrite-static-while-nested.expect +++ b/tests/passes/compile-static/rewrite-static-while-nested.expect @@ -39,6 +39,7 @@ component main(@go go: 1, @clk clk: 1, @reset reset: 1) -> (@done done: 1) { l.right = 3'd6; r_cond.in = l.out; r_cond.write_en = 1'd1; + p.addr0 = 1'd0; adder0.left = fsm0.out; adder0.right = 1'd1; fsm0.write_en = 1'd1; @@ -56,6 +57,7 @@ component main(@go go: 1, @clk clk: 1, @reset reset: 1) -> (@done done: 1) { l.right = fsm1.out == 2'd1 ? 3'd6; r_cond.in = fsm1.out == 2'd1 ? l.out; r_cond.write_en = fsm1.out == 2'd1 ? 1'd1; + p.addr0 = fsm1.out == 2'd1 ? 1'd0; adder1.left = fsm1.out; adder1.right = 2'd1; fsm1.write_en = 1'd1; diff --git a/tests/passes/compile-static/rewrite-static-while-nested.futil b/tests/passes/compile-static/rewrite-static-while-nested.futil index 08ffb8d364..6b60d480ea 100644 --- a/tests/passes/compile-static/rewrite-static-while-nested.futil +++ b/tests/passes/compile-static/rewrite-static-while-nested.futil @@ -27,6 +27,7 @@ component main () -> () { l.right = 3'd6; r_cond.in = l.out; r_cond.write_en = 1'd1; + p.addr0 = 1'd0; } group B { From 1f99a013fdb9547fd4f56081aa9118b7613b4dc6 Mon Sep 17 00:00:00 2001 From: Pai Li Date: Mon, 15 May 2023 16:10:44 -0400 Subject: [PATCH 13/14] get rid of counterexample --- .../static-control/counterexample2.futil | 43 ------------------ .../static-control/counterexample2.futil.data | 12 ----- .../compile-static/counterexample.expect | 6 --- .../compile-static/counterexample.futil | 44 ------------------- 4 files changed, 105 deletions(-) delete mode 100644 tests/correctness/static-control/counterexample2.futil delete mode 100644 tests/correctness/static-control/counterexample2.futil.data delete mode 100644 tests/passes/compile-static/counterexample.expect delete mode 100644 tests/passes/compile-static/counterexample.futil diff --git a/tests/correctness/static-control/counterexample2.futil b/tests/correctness/static-control/counterexample2.futil deleted file mode 100644 index d0968ea6c1..0000000000 --- a/tests/correctness/static-control/counterexample2.futil +++ /dev/null @@ -1,43 +0,0 @@ -import "primitives/core.futil"; -import "primitives/pipelined.futil"; -component main () -> () { - cells { - p = std_reg(5); - w = std_wire(5); - A_exec_wire = std_wire(1); - incr = std_add(5); - l = std_lt(5); - @external mem = std_mem_d1(5, 1, 1); - } - wires { - static group A <1>{ - incr.left = p.out; - incr.right = 5'd1; - p.in = incr.out; - p.write_en = 1'd1; - // let w.out be the input to l.left - w.in = incr.out; - A_exec_wire.in = 1'd1; - } - static group B <1>{ - incr.left = p.out; - incr.right = mem.read_data; - mem.write_data = incr.out; - mem.write_en = 1'd1; - mem.addr0 = 1'd0; - } - w.in = !A_exec_wire.out ? p.out; - l.left = w.out; - l.right = 5'd6; - } - control { - while l.out { - static seq { - A; B; - } - } - } -} - - - diff --git a/tests/correctness/static-control/counterexample2.futil.data b/tests/correctness/static-control/counterexample2.futil.data deleted file mode 100644 index f1f004616e..0000000000 --- a/tests/correctness/static-control/counterexample2.futil.data +++ /dev/null @@ -1,12 +0,0 @@ -{ - "mem": { - "data": [ - 0 - ], - "format": { - "is_signed": false, - "numeric_type": "bitnum", - "width": 5 - } - } -} \ No newline at end of file diff --git a/tests/passes/compile-static/counterexample.expect b/tests/passes/compile-static/counterexample.expect deleted file mode 100644 index a46d4d4b53..0000000000 --- a/tests/passes/compile-static/counterexample.expect +++ /dev/null @@ -1,6 +0,0 @@ ----CODE--- -1 ----STDERR--- -Error: Malformed Control: tests/passes/compile-static/counterexample.futil -38 | while l.out { - | ^^^^^^^^^^^^^ While loop has no comb group and its condition port l.out is unstable diff --git a/tests/passes/compile-static/counterexample.futil b/tests/passes/compile-static/counterexample.futil deleted file mode 100644 index 47312bccae..0000000000 --- a/tests/passes/compile-static/counterexample.futil +++ /dev/null @@ -1,44 +0,0 @@ -// -p well-formed -p static-inline -p compile-static -p dead-group-removal -p remove-ids - -import "primitives/core.futil"; -import "primitives/pipelined.futil"; - -component main () -> () { - cells { - p = std_reg(5); - w = std_wire(5); - incr = std_add(5); - l = std_lt(5); - @external mem = std_mem_d1(5, 1, 1); - } - - wires { - static<1> group A { - incr.left = p.out; - incr.right = 5'd1; - p.in = incr.out; - p.write_en = %0 ? 1'd1; - w.in = %0 ? incr.out; - } - - static<1> group B { - incr.left = p.out; - incr.right = mem.read_data; - mem.write_data = incr.out; - mem.write_en = %0 ? 1'd1; - mem.addr0 = 1'd0; - } - - l.left = w.out; - l.right = 5'd6; - - } - - control { - while l.out { - static seq { - A; B; - } - } - } -} \ No newline at end of file From 8ae05059c585ead7ea641774208f58fbff6f2b1e Mon Sep 17 00:00:00 2001 From: Pai Li Date: Mon, 15 May 2023 16:41:20 -0400 Subject: [PATCH 14/14] fixed test cases --- .../static-control/nested-static-while.expect | 2 +- tests/correctness/static-control/while.expect | 2 +- .../rewrite-static-while-nested.expect | 13 +++---------- .../compile-static/rewrite-static-while.expect | 13 +++---------- 4 files changed, 8 insertions(+), 22 deletions(-) diff --git a/tests/correctness/static-control/nested-static-while.expect b/tests/correctness/static-control/nested-static-while.expect index 3b97cd1c75..a9183afe05 100644 --- a/tests/correctness/static-control/nested-static-while.expect +++ b/tests/correctness/static-control/nested-static-while.expect @@ -1,5 +1,5 @@ { - "cycles": 80, + "cycles": 65, "memories": { "p": [ 6 diff --git a/tests/correctness/static-control/while.expect b/tests/correctness/static-control/while.expect index 4541fc90b0..c74c4510ce 100644 --- a/tests/correctness/static-control/while.expect +++ b/tests/correctness/static-control/while.expect @@ -1,5 +1,5 @@ { - "cycles": 26, + "cycles": 21, "memories": { "p": [ 6 diff --git a/tests/passes/compile-static/rewrite-static-while-nested.expect b/tests/passes/compile-static/rewrite-static-while-nested.expect index e3e9b4b719..e27ecac2eb 100644 --- a/tests/passes/compile-static/rewrite-static-while-nested.expect +++ b/tests/passes/compile-static/rewrite-static-while-nested.expect @@ -18,7 +18,6 @@ component main(@go go: 1, @clk clk: 1, @reset reset: 1) -> (@done done: 1) { @generated ud1 = undef(1); @generated adder1 = std_add(2); @generated signal_reg = std_reg(1); - @generated signal_reg0 = std_reg(1); } wires { group B { @@ -71,11 +70,9 @@ component main(@go go: 1, @clk clk: 1, @reset reset: 1) -> (@done done: 1) { signal_reg.in = fsm0.out == 1'd0 & !signal_reg.out ? 1'd1; wrapper_early_reset_A2[done] = fsm0.out == 1'd0 & signal_reg.out ? 1'd1; } - group wrapper_early_reset_static_seq { + group while_wrapper_early_reset_static_seq { early_reset_static_seq[go] = 1'd1; - signal_reg0.write_en = fsm1.out == 2'd0 & !signal_reg0.out ? 1'd1; - signal_reg0.in = fsm1.out == 2'd0 & !signal_reg0.out ? 1'd1; - wrapper_early_reset_static_seq[done] = fsm1.out == 2'd0 & signal_reg0.out ? 1'd1; + while_wrapper_early_reset_static_seq[done] = !r_cond.out & fsm1.out == 2'd0 ? 1'd1; } comb group comp { l2.left = r.out; @@ -83,8 +80,6 @@ component main(@go go: 1, @clk clk: 1, @reset reset: 1) -> (@done done: 1) { } signal_reg.write_en = fsm0.out == 1'd0 & signal_reg.out ? 1'd1; signal_reg.in = fsm0.out == 1'd0 & signal_reg.out ? 1'd0; - signal_reg0.write_en = fsm1.out == 2'd0 & signal_reg0.out ? 1'd1; - signal_reg0.in = fsm1.out == 2'd0 & signal_reg0.out ? 1'd0; } control { @@ -92,9 +87,7 @@ component main(@go go: 1, @clk clk: 1, @reset reset: 1) -> (@done done: 1) { seq { B; wrapper_early_reset_A2; - while r_cond.out { - wrapper_early_reset_static_seq; - } + while_wrapper_early_reset_static_seq; C; } } diff --git a/tests/passes/compile-static/rewrite-static-while.expect b/tests/passes/compile-static/rewrite-static-while.expect index 108d7a3adb..fe52f0282c 100644 --- a/tests/passes/compile-static/rewrite-static-while.expect +++ b/tests/passes/compile-static/rewrite-static-while.expect @@ -16,7 +16,6 @@ component main(@go go: 1, @clk clk: 1, @reset reset: 1) -> (@done done: 1) { @generated ud1 = undef(1); @generated adder1 = std_add(2); @generated signal_reg = std_reg(1); - @generated signal_reg0 = std_reg(1); } wires { group early_reset_B { @@ -53,24 +52,18 @@ component main(@go go: 1, @clk clk: 1, @reset reset: 1) -> (@done done: 1) { signal_reg.in = fsm0.out == 1'd0 & !signal_reg.out ? 1'd1; wrapper_early_reset_B[done] = fsm0.out == 1'd0 & signal_reg.out ? 1'd1; } - group wrapper_early_reset_static_seq { + group while_wrapper_early_reset_static_seq { early_reset_static_seq[go] = 1'd1; - signal_reg0.write_en = fsm1.out == 2'd0 & !signal_reg0.out ? 1'd1; - signal_reg0.in = fsm1.out == 2'd0 & !signal_reg0.out ? 1'd1; - wrapper_early_reset_static_seq[done] = fsm1.out == 2'd0 & signal_reg0.out ? 1'd1; + while_wrapper_early_reset_static_seq[done] = !r.out & fsm1.out == 2'd0 ? 1'd1; } signal_reg.write_en = fsm0.out == 1'd0 & signal_reg.out ? 1'd1; signal_reg.in = fsm0.out == 1'd0 & signal_reg.out ? 1'd0; - signal_reg0.write_en = fsm1.out == 2'd0 & signal_reg0.out ? 1'd1; - signal_reg0.in = fsm1.out == 2'd0 & signal_reg0.out ? 1'd0; } control { seq { wrapper_early_reset_B; - while r.out { - wrapper_early_reset_static_seq; - } + while_wrapper_early_reset_static_seq; } } }