From 30907da717ec3c75090b83406f66720f24ed8c6f Mon Sep 17 00:00:00 2001 From: Ethan Uppal <113849268+ethanuppal@users.noreply.github.com> Date: Thu, 6 Jun 2024 23:13:11 -0400 Subject: [PATCH 1/9] This actually took me like a week --- calyx-frontend/src/attribute.rs | 4 +++ calyx-opt/src/analysis/promotion_analysis.rs | 2 +- calyx-opt/src/passes/static_promotion.rs | 8 ++++- .../src/passes/top_down_compile_control.rs | 12 ++++++-- temp/Makefile | 4 +++ temp/test.futil | 29 +++++++++++++++++++ 6 files changed, 54 insertions(+), 5 deletions(-) create mode 100644 temp/Makefile create mode 100644 temp/test.futil diff --git a/calyx-frontend/src/attribute.rs b/calyx-frontend/src/attribute.rs index 79e5c76042..3ffe749ef5 100644 --- a/calyx-frontend/src/attribute.rs +++ b/calyx-frontend/src/attribute.rs @@ -69,7 +69,11 @@ pub enum BoolAttr { #[strum(serialize = "promoted")] /// denotes a static component or control promoted from dynamic Promoted, + #[strum(serialize = "fast")] + /// https://github.com/calyxir/calyx/issues/1828 + Fast, } + impl From for Attribute { fn from(attr: BoolAttr) -> Self { Attribute::Bool(attr) diff --git a/calyx-opt/src/analysis/promotion_analysis.rs b/calyx-opt/src/analysis/promotion_analysis.rs index 938ba31aca..adbfd9fa8b 100644 --- a/calyx-opt/src/analysis/promotion_analysis.rs +++ b/calyx-opt/src/analysis/promotion_analysis.rs @@ -1,4 +1,4 @@ -use calyx_ir::{self as ir}; +use calyx_ir::{self as ir, BoolAttr}; use std::collections::HashMap; use std::rc::Rc; diff --git a/calyx-opt/src/passes/static_promotion.rs b/calyx-opt/src/passes/static_promotion.rs index b13c116955..00a64c323c 100644 --- a/calyx-opt/src/passes/static_promotion.rs +++ b/calyx-opt/src/passes/static_promotion.rs @@ -5,7 +5,7 @@ use crate::traversal::{ Action, ConstructVisitor, Named, Order, ParseVal, PassOpt, VisResult, Visitor, }; -use calyx_ir::{self as ir, LibrarySignatures}; +use calyx_ir::{self as ir, BoolAttr, LibrarySignatures}; use calyx_utils::CalyxResult; use ir::GetAttributes; use itertools::Itertools; @@ -490,6 +490,12 @@ impl Visitor for StaticPromotion { }) }; self.inference_analysis.fixup_ctrl(&mut new_ctrl); + + // this might be part of a larger issue where passes remove some attributes they shouldn't + if s.get_attributes().has(BoolAttr::Fast) { + new_ctrl.get_mut_attributes().insert(BoolAttr::Fast, 1); + } + Ok(Action::change(new_ctrl)) } diff --git a/calyx-opt/src/passes/top_down_compile_control.rs b/calyx-opt/src/passes/top_down_compile_control.rs index 872604233a..6525ce7ccf 100644 --- a/calyx-opt/src/passes/top_down_compile_control.rs +++ b/calyx-opt/src/passes/top_down_compile_control.rs @@ -3,7 +3,9 @@ use crate::passes; use crate::traversal::{ Action, ConstructVisitor, Named, ParseVal, PassOpt, VisResult, Visitor, }; -use calyx_ir::{self as ir, GetAttributes, LibrarySignatures, Printer, RRC}; +use calyx_ir::{ + self as ir, BoolAttr, GetAttributes, LibrarySignatures, Printer, RRC, +}; use calyx_ir::{build_assignments, guard, structure, Id}; use calyx_utils::Error; use calyx_utils::{CalyxResult, OutputFile}; @@ -495,7 +497,7 @@ impl Schedule<'_, '_> { // NOTE: We explicilty do not add `not_done` to the guard. // See explanation in [ir::TopDownCompileControl] to understand // why. - if early_transitions { + if early_transitions || con.has_attribute(BoolAttr::Fast) { for (st, g) in &prev_states { let early_go = build_assignments!(self.builder; group["go"] = g ? signal_on["out"]; @@ -1130,7 +1132,11 @@ impl Visitor for TopDownCompileControl { let mut builder = ir::Builder::new(comp, sigs); let mut sch = Schedule::from(&mut builder); // Add assignments for the final states - sch.calculate_states(&control.borrow(), self.early_transitions)?; + sch.calculate_states( + &control.borrow(), + self.early_transitions + || control.borrow().has_attribute(BoolAttr::Fast), + )?; let comp_group = sch.realize_schedule(self.dump_fsm, &mut self.fsm_groups); if let Some(json_out_file) = &self.dump_fsm_json { diff --git a/temp/Makefile b/temp/Makefile new file mode 100644 index 0000000000..7e2fc24542 --- /dev/null +++ b/temp/Makefile @@ -0,0 +1,4 @@ +.PHONY: run +run: + cd .. && cargo build + calyx-pass -e ../target/debug/calyx -c main -b tdcc test.futil diff --git a/temp/test.futil b/temp/test.futil new file mode 100644 index 0000000000..88c70a80e7 --- /dev/null +++ b/temp/test.futil @@ -0,0 +1,29 @@ +import "primitives/core.futil"; +import "primitives/memories/comb.futil"; + +component main(@go go: 1) -> (@done done: 1) { + cells { + @external(1) in_mem = comb_mem_d1(32, 1, 32); + @external(1) out_mem = comb_mem_d1(32, 1, 32); + i0 = std_reg(32); + } + wires { + group d1 { + in_mem.addr0 = 32'd0; + i0.in = in_mem.read_data; + i0.write_en = 1'b1; + d1[done] = i0.done; + } + static<1> group s2 { + in_mem.addr0 = 32'd0; + out_mem.write_data = i0.out; + out_mem.write_en = 1'b1; + } + } + control { + @fast seq { + d1; + s2; + } + } +} From d7dafc48726b549c6c3089eef8fbbdaf428bfb44 Mon Sep 17 00:00:00 2001 From: Ethan Uppal <113849268+ethanuppal@users.noreply.github.com> Date: Fri, 7 Jun 2024 00:25:46 -0400 Subject: [PATCH 2/9] Add well-formed check for @fast --- calyx-opt/src/analysis/promotion_analysis.rs | 2 +- calyx-opt/src/passes/well_formed.rs | 39 +++++++++++++++++++ runt.toml | 23 +++++++++-- temp/test.futil | 1 - temp/test2.futil | 28 +++++++++++++ .../as_least_as_fast/dynamic_static.futil | 28 +++++++++++++ .../as_least_as_fast/static_dynamic.futil | 28 +++++++++++++ .../fast-attr/semantic_preservation/.gitkeep | 0 .../semantic_preservation/README.txt | 1 + 9 files changed, 145 insertions(+), 5 deletions(-) create mode 100644 temp/test2.futil create mode 100644 tests/correctness/fast-attr/as_least_as_fast/dynamic_static.futil create mode 100644 tests/correctness/fast-attr/as_least_as_fast/static_dynamic.futil create mode 100644 tests/correctness/fast-attr/semantic_preservation/.gitkeep create mode 100644 tests/correctness/fast-attr/semantic_preservation/README.txt diff --git a/calyx-opt/src/analysis/promotion_analysis.rs b/calyx-opt/src/analysis/promotion_analysis.rs index adbfd9fa8b..938ba31aca 100644 --- a/calyx-opt/src/analysis/promotion_analysis.rs +++ b/calyx-opt/src/analysis/promotion_analysis.rs @@ -1,4 +1,4 @@ -use calyx_ir::{self as ir, BoolAttr}; +use calyx_ir::{self as ir}; use std::collections::HashMap; use std::rc::Rc; diff --git a/calyx-opt/src/passes/well_formed.rs b/calyx-opt/src/passes/well_formed.rs index ddc9ba06e5..168d3e10dc 100644 --- a/calyx-opt/src/passes/well_formed.rs +++ b/calyx-opt/src/passes/well_formed.rs @@ -3,6 +3,7 @@ use calyx_ir::{ self as ir, CellType, Component, GetAttributes, LibrarySignatures, RESERVED_NAMES, }; +use calyx_ir::{BoolAttr, Seq}; use calyx_utils::{CalyxResult, Error, WithPos}; use ir::Nothing; use ir::StaticTiming; @@ -203,6 +204,30 @@ fn same_type(proto_out: &CellType, proto_in: &CellType) -> CalyxResult<()> { } } +/// Confirms (in agreement with [this discussion](https://github.com/calyxir/calyx/issues/1828)) +/// that the `@fast` sequence `seq` is composed of alternating static-dynamic controls. +fn check_fast_seq_invariant(seq: &Seq) -> CalyxResult<()> { + if seq.stmts.is_empty() { + return Ok(()); + } + let mut last_is_static = seq + .stmts + .first() + .expect("non-empty already asserted") + .is_static(); + for stmt in seq.stmts.iter().skip(1) { + if stmt.is_static() == last_is_static { + return Err( + Error::malformed_control( + "`seq` marked `@fast` does not contain alternating static-dynamic control children (see #1828)" + ) + ); + } + last_is_static = stmt.is_static(); + } + Ok(()) +} + impl Visitor for WellFormed { fn start( &mut self, @@ -680,6 +705,20 @@ impl Visitor for WellFormed { Ok(Action::Continue) } + fn start_seq( + &mut self, + s: &mut calyx_ir::Seq, + _comp: &mut Component, + _sigs: &LibrarySignatures, + _comps: &[calyx_ir::Component], + ) -> VisResult { + if s.attributes.has(BoolAttr::Fast) { + check_fast_seq_invariant(s)?; + } + + Ok(Action::Continue) + } + fn finish_if( &mut self, s: &mut ir::If, diff --git a/runt.toml b/runt.toml index 9b1fda3484..09bd73e520 100644 --- a/runt.toml +++ b/runt.toml @@ -233,9 +233,7 @@ timeout = 120 [[tests]] name = "correctness static timing one-hot encoding" -paths = [ - "tests/correctness/static-interface/*.futil", -] +paths = ["tests/correctness/static-interface/*.futil"] cmd = """ fud exec --from calyx --to jq \ --through verilog \ @@ -334,6 +332,25 @@ fud exec --from calyx --to jq \ {} -q """ +# todo: need to test that removing @fast (e.g. using sed) causes >= cycles +# +# Copilot said: +# # Replace 'command1' and 'command2' with your actual commands +# [[ $(command1) -le $(command2) ]] && echo "true" || echo "false" +# +# [[tests]] +# name = "correctness: @fast improves speed" +# paths = ["tests/correctness/fast-attr/at_least_as_fast/*.futil"] +# cmd = """ +# fud exec --from calyx --to jq \ +# --through dat \ +# --through verilog \ +# -s verilog.data {}.data \ +# -s calyx.flags "-d static-promotion" \ +# -s jq.expr ".cycles" \ +# {} -q +# """ + [[tests]] name = "[frontend] tcam testing" paths = ["tests/correctness/tcam/*.futil"] diff --git a/temp/test.futil b/temp/test.futil index 88c70a80e7..ab6e0a01ef 100644 --- a/temp/test.futil +++ b/temp/test.futil @@ -15,7 +15,6 @@ component main(@go go: 1) -> (@done done: 1) { d1[done] = i0.done; } static<1> group s2 { - in_mem.addr0 = 32'd0; out_mem.write_data = i0.out; out_mem.write_en = 1'b1; } diff --git a/temp/test2.futil b/temp/test2.futil new file mode 100644 index 0000000000..e7e55d245e --- /dev/null +++ b/temp/test2.futil @@ -0,0 +1,28 @@ +import "primitives/core.futil"; +import "primitives/memories/comb.futil"; + +component main(@go go: 1) -> (@done done: 1) { + cells { + @external(1) in_mem = comb_mem_d1(32, 1, 32); + @external(1) out_mem = comb_mem_d1(32, 1, 32); + i0 = std_reg(32); + } + wires { + static<1> group s1 { + in_mem.addr0 = 32'd0; + i0.in = in_mem.read_data; + i0.write_en = 1'b1; + } + group d2 { + out_mem.write_data = i0.out; + out_mem.write_en = 1'b1; + d2[done] = out_mem.done; + } + } + control { + @fast seq { + s1; + d2; + } + } +} diff --git a/tests/correctness/fast-attr/as_least_as_fast/dynamic_static.futil b/tests/correctness/fast-attr/as_least_as_fast/dynamic_static.futil new file mode 100644 index 0000000000..ab6e0a01ef --- /dev/null +++ b/tests/correctness/fast-attr/as_least_as_fast/dynamic_static.futil @@ -0,0 +1,28 @@ +import "primitives/core.futil"; +import "primitives/memories/comb.futil"; + +component main(@go go: 1) -> (@done done: 1) { + cells { + @external(1) in_mem = comb_mem_d1(32, 1, 32); + @external(1) out_mem = comb_mem_d1(32, 1, 32); + i0 = std_reg(32); + } + wires { + group d1 { + in_mem.addr0 = 32'd0; + i0.in = in_mem.read_data; + i0.write_en = 1'b1; + d1[done] = i0.done; + } + static<1> group s2 { + out_mem.write_data = i0.out; + out_mem.write_en = 1'b1; + } + } + control { + @fast seq { + d1; + s2; + } + } +} diff --git a/tests/correctness/fast-attr/as_least_as_fast/static_dynamic.futil b/tests/correctness/fast-attr/as_least_as_fast/static_dynamic.futil new file mode 100644 index 0000000000..e7e55d245e --- /dev/null +++ b/tests/correctness/fast-attr/as_least_as_fast/static_dynamic.futil @@ -0,0 +1,28 @@ +import "primitives/core.futil"; +import "primitives/memories/comb.futil"; + +component main(@go go: 1) -> (@done done: 1) { + cells { + @external(1) in_mem = comb_mem_d1(32, 1, 32); + @external(1) out_mem = comb_mem_d1(32, 1, 32); + i0 = std_reg(32); + } + wires { + static<1> group s1 { + in_mem.addr0 = 32'd0; + i0.in = in_mem.read_data; + i0.write_en = 1'b1; + } + group d2 { + out_mem.write_data = i0.out; + out_mem.write_en = 1'b1; + d2[done] = out_mem.done; + } + } + control { + @fast seq { + s1; + d2; + } + } +} diff --git a/tests/correctness/fast-attr/semantic_preservation/.gitkeep b/tests/correctness/fast-attr/semantic_preservation/.gitkeep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/correctness/fast-attr/semantic_preservation/README.txt b/tests/correctness/fast-attr/semantic_preservation/README.txt new file mode 100644 index 0000000000..707588bd03 --- /dev/null +++ b/tests/correctness/fast-attr/semantic_preservation/README.txt @@ -0,0 +1 @@ +TODO: tests that using `@fast` does not change the function of the program From 0ecda0c311684c40ef16afbbc6b39e2a0738bc9e Mon Sep 17 00:00:00 2001 From: Ethan Uppal <113849268+ethanuppal@users.noreply.github.com> Date: Mon, 10 Jun 2024 12:07:37 -0400 Subject: [PATCH 3/9] Prevent from cascading --- .../src/passes/top_down_compile_control.rs | 24 ++++++++++++------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/calyx-opt/src/passes/top_down_compile_control.rs b/calyx-opt/src/passes/top_down_compile_control.rs index 6525ce7ccf..e2c2f783ef 100644 --- a/calyx-opt/src/passes/top_down_compile_control.rs +++ b/calyx-opt/src/passes/top_down_compile_control.rs @@ -462,6 +462,8 @@ impl Schedule<'_, '_> { preds: Vec, // True if early_transitions are allowed early_transitions: bool, + // True if the `@fast` attribute has successfully been applied to the parent of this control + has_fast_guarantee: bool, ) -> CalyxResult> { match con { // See explanation of FSM states generated in [ir::TopDownCompileControl]. @@ -497,7 +499,7 @@ impl Schedule<'_, '_> { // NOTE: We explicilty do not add `not_done` to the guard. // See explanation in [ir::TopDownCompileControl] to understand // why. - if early_transitions || con.has_attribute(BoolAttr::Fast) { + if early_transitions || has_fast_guarantee { for (st, g) in &prev_states { let early_go = build_assignments!(self.builder; group["go"] = g ? signal_on["out"]; @@ -544,9 +546,13 @@ impl Schedule<'_, '_> { early_transitions: bool, ) -> CalyxResult> { let mut prev = preds; - for stmt in &seq.stmts { - prev = - self.calculate_states_recur(stmt, prev, early_transitions)?; + for (i, stmt) in seq.stmts.iter().enumerate() { + prev = self.calculate_states_recur( + stmt, + prev, + early_transitions, + i > 0 && seq.get_attributes().has(BoolAttr::Fast), + )?; } Ok(prev) } @@ -579,6 +585,7 @@ impl Schedule<'_, '_> { &if_stmt.tbranch, tru_transitions, early_transitions, + false, )?; // Previous states transitioning into false branch need the conditional // to be false. @@ -596,6 +603,7 @@ impl Schedule<'_, '_> { &if_stmt.fbranch, fal_transitions, early_transitions, + false, )? }; @@ -638,6 +646,7 @@ impl Schedule<'_, '_> { &while_stmt.body, transitions, early_transitions, + false, )?; // Step 3: The final out edges from the while come from: @@ -742,6 +751,7 @@ impl Schedule<'_, '_> { con, vec![first_state], early_transitions, + false, )?; self.add_nxt_transition(prev); Ok(()) @@ -1132,11 +1142,7 @@ impl Visitor for TopDownCompileControl { let mut builder = ir::Builder::new(comp, sigs); let mut sch = Schedule::from(&mut builder); // Add assignments for the final states - sch.calculate_states( - &control.borrow(), - self.early_transitions - || control.borrow().has_attribute(BoolAttr::Fast), - )?; + sch.calculate_states(&control.borrow(), self.early_transitions)?; let comp_group = sch.realize_schedule(self.dump_fsm, &mut self.fsm_groups); if let Some(json_out_file) = &self.dump_fsm_json { From 70e25d6b16040577fa5a320ccd7211db6a56368d Mon Sep 17 00:00:00 2001 From: Ethan Uppal <113849268+ethanuppal@users.noreply.github.com> Date: Mon, 10 Jun 2024 12:11:58 -0400 Subject: [PATCH 4/9] Forgot to remove these --- runt.toml | 19 ------------- .../as_least_as_fast/dynamic_static.futil | 28 ------------------- .../as_least_as_fast/static_dynamic.futil | 28 ------------------- .../fast-attr/semantic_preservation/.gitkeep | 0 .../semantic_preservation/README.txt | 1 - 5 files changed, 76 deletions(-) delete mode 100644 tests/correctness/fast-attr/as_least_as_fast/dynamic_static.futil delete mode 100644 tests/correctness/fast-attr/as_least_as_fast/static_dynamic.futil delete mode 100644 tests/correctness/fast-attr/semantic_preservation/.gitkeep delete mode 100644 tests/correctness/fast-attr/semantic_preservation/README.txt diff --git a/runt.toml b/runt.toml index e14ca3a6ab..7b1e5c4080 100644 --- a/runt.toml +++ b/runt.toml @@ -332,25 +332,6 @@ fud exec --from calyx --to jq \ {} -q """ -# todo: need to test that removing @fast (e.g. using sed) causes >= cycles -# -# Copilot said: -# # Replace 'command1' and 'command2' with your actual commands -# [[ $(command1) -le $(command2) ]] && echo "true" || echo "false" -# -# [[tests]] -# name = "correctness: @fast improves speed" -# paths = ["tests/correctness/fast-attr/at_least_as_fast/*.futil"] -# cmd = """ -# fud exec --from calyx --to jq \ -# --through dat \ -# --through verilog \ -# -s verilog.data {}.data \ -# -s calyx.flags "-d static-promotion" \ -# -s jq.expr ".cycles" \ -# {} -q -# """ - [[tests]] name = "[frontend] tcam testing" paths = ["tests/correctness/tcam/*.futil"] diff --git a/tests/correctness/fast-attr/as_least_as_fast/dynamic_static.futil b/tests/correctness/fast-attr/as_least_as_fast/dynamic_static.futil deleted file mode 100644 index ab6e0a01ef..0000000000 --- a/tests/correctness/fast-attr/as_least_as_fast/dynamic_static.futil +++ /dev/null @@ -1,28 +0,0 @@ -import "primitives/core.futil"; -import "primitives/memories/comb.futil"; - -component main(@go go: 1) -> (@done done: 1) { - cells { - @external(1) in_mem = comb_mem_d1(32, 1, 32); - @external(1) out_mem = comb_mem_d1(32, 1, 32); - i0 = std_reg(32); - } - wires { - group d1 { - in_mem.addr0 = 32'd0; - i0.in = in_mem.read_data; - i0.write_en = 1'b1; - d1[done] = i0.done; - } - static<1> group s2 { - out_mem.write_data = i0.out; - out_mem.write_en = 1'b1; - } - } - control { - @fast seq { - d1; - s2; - } - } -} diff --git a/tests/correctness/fast-attr/as_least_as_fast/static_dynamic.futil b/tests/correctness/fast-attr/as_least_as_fast/static_dynamic.futil deleted file mode 100644 index e7e55d245e..0000000000 --- a/tests/correctness/fast-attr/as_least_as_fast/static_dynamic.futil +++ /dev/null @@ -1,28 +0,0 @@ -import "primitives/core.futil"; -import "primitives/memories/comb.futil"; - -component main(@go go: 1) -> (@done done: 1) { - cells { - @external(1) in_mem = comb_mem_d1(32, 1, 32); - @external(1) out_mem = comb_mem_d1(32, 1, 32); - i0 = std_reg(32); - } - wires { - static<1> group s1 { - in_mem.addr0 = 32'd0; - i0.in = in_mem.read_data; - i0.write_en = 1'b1; - } - group d2 { - out_mem.write_data = i0.out; - out_mem.write_en = 1'b1; - d2[done] = out_mem.done; - } - } - control { - @fast seq { - s1; - d2; - } - } -} diff --git a/tests/correctness/fast-attr/semantic_preservation/.gitkeep b/tests/correctness/fast-attr/semantic_preservation/.gitkeep deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/tests/correctness/fast-attr/semantic_preservation/README.txt b/tests/correctness/fast-attr/semantic_preservation/README.txt deleted file mode 100644 index 707588bd03..0000000000 --- a/tests/correctness/fast-attr/semantic_preservation/README.txt +++ /dev/null @@ -1 +0,0 @@ -TODO: tests that using `@fast` does not change the function of the program From 2ee19f793f1addef11211956b1ccf0bac0cfa367 Mon Sep 17 00:00:00 2001 From: Ethan Uppal <113849268+ethanuppal@users.noreply.github.com> Date: Mon, 10 Jun 2024 13:11:37 -0400 Subject: [PATCH 5/9] Add basic tests --- runt.toml | 26 +++++++++++ temp/Makefile | 4 -- temp/test.futil | 28 ----------- temp/test2.futil | 28 ----------- .../fast-attr/invalid/invalid.expect | 9 ++++ .../fast-attr/invalid/invalid.futil | 46 +++++++++++++++++++ .../fast-attr/invalid/invalid.futil.data | 12 +++++ .../fast-attr/valid/fast6inc.expect | 5 ++ .../fast-attr/valid/fast6inc.futil | 46 +++++++++++++++++++ .../fast-attr/valid/fast6inc.futil.data | 12 +++++ 10 files changed, 156 insertions(+), 60 deletions(-) delete mode 100644 temp/Makefile delete mode 100644 temp/test.futil delete mode 100644 temp/test2.futil create mode 100644 tests/correctness/fast-attr/invalid/invalid.expect create mode 100644 tests/correctness/fast-attr/invalid/invalid.futil create mode 100644 tests/correctness/fast-attr/invalid/invalid.futil.data create mode 100644 tests/correctness/fast-attr/valid/fast6inc.expect create mode 100644 tests/correctness/fast-attr/valid/fast6inc.futil create mode 100644 tests/correctness/fast-attr/valid/fast6inc.futil.data diff --git a/runt.toml b/runt.toml index 7b1e5c4080..4afad75fa8 100644 --- a/runt.toml +++ b/runt.toml @@ -388,6 +388,32 @@ fud e --from systolic --to jq \ """ expect_dir = "tests/correctness/systolic/mmult-expect" +[[tests]] +name = "[correctness] `@fast` attribute should not change program behavior" +paths = ["tests/correctness/fast-attr/valid/*.futil"] +cmd = """ +fud exec --from calyx --to jq \ + --through dat \ + --through icarus-verilog \ + -s calyx.flags "-p validate -p compile -p lower" \ + -s verilog.data {}.data \ + -s jq.expr ".memories" \ + {} -q +""" + +[[tests]] +name = "[correctness] `@fast` attribute should reject unoptimizable sequences" +paths = ["tests/correctness/fast-attr/invalid/*.futil"] +cmd = """ +fud exec --from calyx --to jq \ + --through dat \ + --through icarus-verilog \ + -s calyx.flags "-p validate -p compile -p lower" \ + -s verilog.data {}.data \ + -s jq.expr ".memories" \ + {} -q +""" + [[tests]] name = "[frontend] systolic array relu static correctness" paths = ["tests/correctness/systolic/relu-inputs/*.data"] diff --git a/temp/Makefile b/temp/Makefile deleted file mode 100644 index 7e2fc24542..0000000000 --- a/temp/Makefile +++ /dev/null @@ -1,4 +0,0 @@ -.PHONY: run -run: - cd .. && cargo build - calyx-pass -e ../target/debug/calyx -c main -b tdcc test.futil diff --git a/temp/test.futil b/temp/test.futil deleted file mode 100644 index ab6e0a01ef..0000000000 --- a/temp/test.futil +++ /dev/null @@ -1,28 +0,0 @@ -import "primitives/core.futil"; -import "primitives/memories/comb.futil"; - -component main(@go go: 1) -> (@done done: 1) { - cells { - @external(1) in_mem = comb_mem_d1(32, 1, 32); - @external(1) out_mem = comb_mem_d1(32, 1, 32); - i0 = std_reg(32); - } - wires { - group d1 { - in_mem.addr0 = 32'd0; - i0.in = in_mem.read_data; - i0.write_en = 1'b1; - d1[done] = i0.done; - } - static<1> group s2 { - out_mem.write_data = i0.out; - out_mem.write_en = 1'b1; - } - } - control { - @fast seq { - d1; - s2; - } - } -} diff --git a/temp/test2.futil b/temp/test2.futil deleted file mode 100644 index e7e55d245e..0000000000 --- a/temp/test2.futil +++ /dev/null @@ -1,28 +0,0 @@ -import "primitives/core.futil"; -import "primitives/memories/comb.futil"; - -component main(@go go: 1) -> (@done done: 1) { - cells { - @external(1) in_mem = comb_mem_d1(32, 1, 32); - @external(1) out_mem = comb_mem_d1(32, 1, 32); - i0 = std_reg(32); - } - wires { - static<1> group s1 { - in_mem.addr0 = 32'd0; - i0.in = in_mem.read_data; - i0.write_en = 1'b1; - } - group d2 { - out_mem.write_data = i0.out; - out_mem.write_en = 1'b1; - d2[done] = out_mem.done; - } - } - control { - @fast seq { - s1; - d2; - } - } -} diff --git a/tests/correctness/fast-attr/invalid/invalid.expect b/tests/correctness/fast-attr/invalid/invalid.expect new file mode 100644 index 0000000000..9108f31eb7 --- /dev/null +++ b/tests/correctness/fast-attr/invalid/invalid.expect @@ -0,0 +1,9 @@ +---CODE--- +255 +---STDERR--- +[fud] ERROR: `/Users/ethan/Documents/GitHub/calyx/target/debug/calyx -l /Users/ethan/Documents/GitHub/calyx -b verilog --disable-verify -p validate -p compile -p lower' failed: +=====STDERR===== +Error: Malformed Control: `seq` marked `@fast` does not contain alternating static-dynamic control children (see #1828) + +=====STDOUT===== + diff --git a/tests/correctness/fast-attr/invalid/invalid.futil b/tests/correctness/fast-attr/invalid/invalid.futil new file mode 100644 index 0000000000..bedbd75fc8 --- /dev/null +++ b/tests/correctness/fast-attr/invalid/invalid.futil @@ -0,0 +1,46 @@ +import "primitives/core.futil"; +import "primitives/memories/comb.futil"; + +component main(@go go: 1) -> (@done done: 1) { + cells { + @external m = comb_mem_d1(32, 1, 32); + i0 = std_reg(32); + add = std_add(32); + } + wires { + static<1> group init { + i0.in = 32'd0; + i0.write_en = 1'b1; + } + group dyn_inc { + add.left = i0.out; + add.right = 32'd1; + i0.in = add.out; + i0.write_en = 1'b1; + dyn_inc[done] = i0.done; + } + static<1> group static_inc { + add.left = i0.out; + add.right = 32'd1; + i0.in = add.out; + i0.write_en = 1'b1; + } + group write { + m.write_data = i0.out; + m.write_en = 1'b1; + write[done] = m.done; + } + } + control { + @fast seq { + init; + dyn_inc; + dyn_inc; + dyn_inc; + static_inc; + static_inc; + static_inc; + write; + } + } +} diff --git a/tests/correctness/fast-attr/invalid/invalid.futil.data b/tests/correctness/fast-attr/invalid/invalid.futil.data new file mode 100644 index 0000000000..478b067a84 --- /dev/null +++ b/tests/correctness/fast-attr/invalid/invalid.futil.data @@ -0,0 +1,12 @@ +{ + "m": { + "data": [ + 0 + ], + "format": { + "numeric_type": "bitnum", + "is_signed": false, + "width": 32 + } + } +} diff --git a/tests/correctness/fast-attr/valid/fast6inc.expect b/tests/correctness/fast-attr/valid/fast6inc.expect new file mode 100644 index 0000000000..91474f14fb --- /dev/null +++ b/tests/correctness/fast-attr/valid/fast6inc.expect @@ -0,0 +1,5 @@ +{ + "m": [ + 6 + ] +} diff --git a/tests/correctness/fast-attr/valid/fast6inc.futil b/tests/correctness/fast-attr/valid/fast6inc.futil new file mode 100644 index 0000000000..4579d81e5c --- /dev/null +++ b/tests/correctness/fast-attr/valid/fast6inc.futil @@ -0,0 +1,46 @@ +import "primitives/core.futil"; +import "primitives/memories/comb.futil"; + +component main(@go go: 1) -> (@done done: 1) { + cells { + @external m = comb_mem_d1(32, 1, 32); + i0 = std_reg(32); + add = std_add(32); + } + wires { + static<1> group init { + i0.in = 32'd0; + i0.write_en = 1'b1; + } + group dyn_inc { + add.left = i0.out; + add.right = 32'd1; + i0.in = add.out; + i0.write_en = 1'b1; + dyn_inc[done] = i0.done; + } + static<1> group static_inc { + add.left = i0.out; + add.right = 32'd1; + i0.in = add.out; + i0.write_en = 1'b1; + } + group write { + m.write_data = i0.out; + m.write_en = 1'b1; + write[done] = m.done; + } + } + control { + @fast seq { + init; + dyn_inc; + static_inc; + dyn_inc; + static_inc; + dyn_inc; + static_inc; + write; + } + } +} diff --git a/tests/correctness/fast-attr/valid/fast6inc.futil.data b/tests/correctness/fast-attr/valid/fast6inc.futil.data new file mode 100644 index 0000000000..478b067a84 --- /dev/null +++ b/tests/correctness/fast-attr/valid/fast6inc.futil.data @@ -0,0 +1,12 @@ +{ + "m": { + "data": [ + 0 + ], + "format": { + "numeric_type": "bitnum", + "is_signed": false, + "width": 32 + } + } +} From 53e567f56e23956bdf3023f91689f544e99592d6 Mon Sep 17 00:00:00 2001 From: Ethan Uppal <113849268+ethanuppal@users.noreply.github.com> Date: Mon, 10 Jun 2024 15:37:24 -0400 Subject: [PATCH 6/9] There has to be a better way --- tests/correctness/fast-attr/invalid/invalid.expect | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/correctness/fast-attr/invalid/invalid.expect b/tests/correctness/fast-attr/invalid/invalid.expect index 9108f31eb7..44bcbc349b 100644 --- a/tests/correctness/fast-attr/invalid/invalid.expect +++ b/tests/correctness/fast-attr/invalid/invalid.expect @@ -1,7 +1,7 @@ ---CODE--- 255 ---STDERR--- -[fud] ERROR: `/Users/ethan/Documents/GitHub/calyx/target/debug/calyx -l /Users/ethan/Documents/GitHub/calyx -b verilog --disable-verify -p validate -p compile -p lower' failed: +[fud] ERROR: `/home/calyx/target/debug/calyx -l /home/calyx -b verilog --disable-verify -p validate -p compile -p lower' failed: =====STDERR===== Error: Malformed Control: `seq` marked `@fast` does not contain alternating static-dynamic control children (see #1828) From 7b6c8375830b261b84c3523c0c6fce7395459dab Mon Sep 17 00:00:00 2001 From: Ethan Uppal <113849268+ethanuppal@users.noreply.github.com> Date: Sat, 15 Jun 2024 19:19:18 -0400 Subject: [PATCH 7/9] Implement Rachit and Caleb's reviews --- runt.toml | 8 ++--- .../fast-attr/valid/fast6inc.expect | 9 +++-- tools/cache/cache.futil | 34 +++++++++++++++++++ 3 files changed, 44 insertions(+), 7 deletions(-) create mode 100644 tools/cache/cache.futil diff --git a/runt.toml b/runt.toml index 4afad75fa8..e9d91739e6 100644 --- a/runt.toml +++ b/runt.toml @@ -395,9 +395,9 @@ cmd = """ fud exec --from calyx --to jq \ --through dat \ --through icarus-verilog \ - -s calyx.flags "-p validate -p compile -p lower" \ + -s calyx.flags "-p validate -p compile -p lower -d static-promotion" \ -s verilog.data {}.data \ - -s jq.expr ".memories" \ + -s jq.expr "." \ {} -q """ @@ -408,9 +408,9 @@ cmd = """ fud exec --from calyx --to jq \ --through dat \ --through icarus-verilog \ - -s calyx.flags "-p validate -p compile -p lower" \ + -s calyx.flags "-p validate -p compile -p lower -d static-promotion" \ -s verilog.data {}.data \ - -s jq.expr ".memories" \ + -s jq.expr "." \ {} -q """ diff --git a/tests/correctness/fast-attr/valid/fast6inc.expect b/tests/correctness/fast-attr/valid/fast6inc.expect index 91474f14fb..b9f64f9677 100644 --- a/tests/correctness/fast-attr/valid/fast6inc.expect +++ b/tests/correctness/fast-attr/valid/fast6inc.expect @@ -1,5 +1,8 @@ { - "m": [ - 6 - ] + "cycles": 9, + "memories": { + "m": [ + 6 + ] + } } diff --git a/tools/cache/cache.futil b/tools/cache/cache.futil new file mode 100644 index 0000000000..2be1efd52e --- /dev/null +++ b/tools/cache/cache.futil @@ -0,0 +1,34 @@ +// This file was generated +import "primitives/core.futil"; +import "primitives/memories/seq.futil"; + +// dummy main +component main() -> () { + cells {} + wires {} + control {} +} + +$define ADDRESS_WIDTH 16 +$define EXTRA_BITS 2 + +$define L1_TAG_BITS 8 +$define L1_INDEX_BITS 6 +$define L1_BLOCKS_PER_SET 4 +$define L1_BLOCK_SIZE 4 + +// entry = [ valid bit | dirty bit | tag bits | block bits ] +$define L1_ENTRY_BITS EXTRA_BITS + L1_TAG_BITS + L1_INDEX_BITS + L1_BLOCKS_PER_SET * L1_BLOCK_SIZE * 8 +$define L1_NUM_ENTRIES 2 ^ L1_INDEX_BITS + +component cache_level_L1(@go(1) read_go: 1, @go(2) write_go: 1) -> ( + @done(1) read_done: 1, + @done(2) write_done: 1 +) { + cells { + entries = seq_mem_d1($L1_ENTRY_BITS, $L1_NUM_ENTRIES, $L1_INDEX_BITS); + } + wires {} + control {} +} + From 0b9344781bfb6fdd86c07933cff5d0e756880889 Mon Sep 17 00:00:00 2001 From: Ethan Uppal <113849268+ethanuppal@users.noreply.github.com> Date: Sun, 16 Jun 2024 18:06:16 -0400 Subject: [PATCH 8/9] Oops --- tests/correctness/fast-attr/invalid/invalid.expect | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/correctness/fast-attr/invalid/invalid.expect b/tests/correctness/fast-attr/invalid/invalid.expect index 44bcbc349b..d39716899f 100644 --- a/tests/correctness/fast-attr/invalid/invalid.expect +++ b/tests/correctness/fast-attr/invalid/invalid.expect @@ -1,7 +1,7 @@ ---CODE--- 255 ---STDERR--- -[fud] ERROR: `/home/calyx/target/debug/calyx -l /home/calyx -b verilog --disable-verify -p validate -p compile -p lower' failed: +[fud] ERROR: `/home/calyx/target/debug/calyx -l /home/calyx -b verilog --disable-verify -p validate -p compile -p lower -d static-promotion' failed: =====STDERR===== Error: Malformed Control: `seq` marked `@fast` does not contain alternating static-dynamic control children (see #1828) From 648728d15748b8f9652f9bb7736a81f1837fe516 Mon Sep 17 00:00:00 2001 From: Ethan Uppal <113849268+ethanuppal@users.noreply.github.com> Date: Mon, 5 Aug 2024 20:01:13 -0400 Subject: [PATCH 9/9] Remove erroneous file --- tools/cache/cache.futil | 34 ---------------------------------- 1 file changed, 34 deletions(-) delete mode 100644 tools/cache/cache.futil diff --git a/tools/cache/cache.futil b/tools/cache/cache.futil deleted file mode 100644 index 2be1efd52e..0000000000 --- a/tools/cache/cache.futil +++ /dev/null @@ -1,34 +0,0 @@ -// This file was generated -import "primitives/core.futil"; -import "primitives/memories/seq.futil"; - -// dummy main -component main() -> () { - cells {} - wires {} - control {} -} - -$define ADDRESS_WIDTH 16 -$define EXTRA_BITS 2 - -$define L1_TAG_BITS 8 -$define L1_INDEX_BITS 6 -$define L1_BLOCKS_PER_SET 4 -$define L1_BLOCK_SIZE 4 - -// entry = [ valid bit | dirty bit | tag bits | block bits ] -$define L1_ENTRY_BITS EXTRA_BITS + L1_TAG_BITS + L1_INDEX_BITS + L1_BLOCKS_PER_SET * L1_BLOCK_SIZE * 8 -$define L1_NUM_ENTRIES 2 ^ L1_INDEX_BITS - -component cache_level_L1(@go(1) read_go: 1, @go(2) write_go: 1) -> ( - @done(1) read_done: 1, - @done(2) write_done: 1 -) { - cells { - entries = seq_mem_d1($L1_ENTRY_BITS, $L1_NUM_ENTRIES, $L1_INDEX_BITS); - } - wires {} - control {} -} -