diff --git a/airgen/src/lib.rs b/airgen/src/lib.rs index bd7fbeee00..31f7e73e66 100644 --- a/airgen/src/lib.rs +++ b/airgen/src/lib.rs @@ -5,11 +5,11 @@ use std::collections::BTreeMap; use powdr_ast::{ - asm_analysis::{self, combine_flags, AnalysisASMFile, LinkDefinition, MachineDegree}, + asm_analysis::{self, combine_flags, AnalysisASMFile, LinkDefinition}, object::{Link, LinkFrom, LinkTo, Location, Machine, MachineInstanceGraph, Object, Operation}, parsed::{ asm::{parse_absolute_path, AbsoluteSymbolPath, CallableRef, MachineParams}, - Expression, PilStatement, + Expression, NamespaceDegree, PilStatement, }, }; @@ -18,6 +18,8 @@ use itertools::Itertools; use powdr_analysis::utils::parse_pil_statement; +use powdr_number::BigUint; + const MAIN_MACHINE: &str = "::Main"; const MAIN_FUNCTION: &str = "main"; @@ -41,10 +43,24 @@ pub fn compile(input: AnalysisASMFile) -> MachineInstanceGraph { operation_id: None, call_selectors: None, }; + let zero_expr = Expression::from(BigUint::from(0u8)); + let degree = NamespaceDegree { + min: zero_expr.clone(), + max: zero_expr, + }; + + let obj: Object = Object { + degree, + pil: Default::default(), + links: Default::default(), + latch: Default::default(), + call_selectors: Default::default(), + has_pc: Default::default(), + }; return MachineInstanceGraph { main, entry_points: Default::default(), - objects: [(main_location, Default::default())].into(), + objects: [(main_location, obj)].into(), statements: module_level_pil_statements(input), }; } @@ -301,7 +317,16 @@ impl<'a> ASMPILConverter<'a> { // the passed degrees have priority over the ones defined in the machine type let min = instance.min_degree.clone().or(input.degree.min); let max = instance.max_degree.clone().or(input.degree.max); - let degree = MachineDegree { min, max }; + let degree = NamespaceDegree { + min: min.expect(&format!( + "No min_degree set for machine instance {}", + self.location + )), + max: max.expect(&format!( + "No max_degree set for machine instance {}", + self.location + )), + }; self.submachines = input .submachines diff --git a/ast/src/object/mod.rs b/ast/src/object/mod.rs index 472677e19f..79821d28e8 100644 --- a/ast/src/object/mod.rs +++ b/ast/src/object/mod.rs @@ -2,12 +2,9 @@ use std::collections::BTreeMap; use powdr_number::BigUint; -use crate::{ - asm_analysis::MachineDegree, - parsed::{ - asm::{AbsoluteSymbolPath, CallableParams, OperationParams}, - Expression, PilStatement, - }, +use crate::parsed::{ + asm::{AbsoluteSymbolPath, CallableParams, OperationParams}, + Expression, NamespaceDegree, PilStatement, }; mod display; @@ -49,9 +46,9 @@ pub struct MachineInstanceGraph { pub statements: BTreeMap>, } -#[derive(Default, Clone)] +#[derive(Clone)] pub struct Object { - pub degree: MachineDegree, + pub degree: NamespaceDegree, /// the pil identities for this machine pub pil: Vec, /// the links from this machine to its children diff --git a/ast/src/parsed/mod.rs b/ast/src/parsed/mod.rs index 76ef068711..893c16fec2 100644 --- a/ast/src/parsed/mod.rs +++ b/ast/src/parsed/mod.rs @@ -73,6 +73,13 @@ pub struct NamespaceDegree { pub max: Expression, } +impl NamespaceDegree { + pub fn is_static(&self) -> bool { + // we use expression equality here, so `2 + 2 != 4` + self.min == self.max + } +} + impl Children for NamespaceDegree { fn children(&self) -> Box + '_> { Box::new(once(&self.min).chain(once(&self.max))) diff --git a/linker/src/lib.rs b/linker/src/lib.rs index ce3c41d1e4..9e8aab98be 100644 --- a/linker/src/lib.rs +++ b/linker/src/lib.rs @@ -1,51 +1,19 @@ #![deny(clippy::print_stdout)] -use lazy_static::lazy_static; use powdr_analysis::utils::parse_pil_statement; use powdr_ast::{ - asm_analysis::{combine_flags, MachineDegree}, + asm_analysis::combine_flags, object::{Link, Location, MachineInstanceGraph}, parsed::{ asm::{AbsoluteSymbolPath, SymbolPath}, build::{index_access, lookup, namespaced_reference, permutation, selected}, - ArrayLiteral, Expression, NamespaceDegree, PILFile, PilStatement, + ArrayLiteral, PILFile, PilStatement, }, }; use powdr_parser_util::SourceRef; use std::{collections::BTreeMap, iter::once}; const MAIN_OPERATION_NAME: &str = "main"; -/// The log of the default minimum degree -pub const MIN_DEGREE_LOG: usize = 5; -lazy_static! { - // The maximum degree can add a significant cost during setup, because - // the fixed columns need to be committed to in all sizes up to the max degree. - // This gives the user the possibility to overwrite the default value. - /// The log of the default maximum degree - pub static ref MAX_DEGREE_LOG: usize = { - let default_max_degree_log = 22; - - let max_degree_log = match std::env::var("MAX_DEGREE_LOG") { - Ok(val) => val.parse::().unwrap(), - Err(_) => default_max_degree_log, - }; - log::info!("For variably-sized machine, the maximum degree is 2^{max_degree_log}. \ - You can set the environment variable MAX_DEGREE_LOG to change this value."); - max_degree_log - }; -} - -/// Convert a [MachineDegree] into a [NamespaceDegree], setting any unset bounds to the relevant default values -fn to_namespace_degree(d: MachineDegree) -> NamespaceDegree { - NamespaceDegree { - min: d - .min - .unwrap_or_else(|| Expression::from(1 << MIN_DEGREE_LOG)), - max: d - .max - .unwrap_or_else(|| Expression::from(1 << *MAX_DEGREE_LOG)), - } -} /// The optional degree of the namespace is set to that of the object if it's set, to that of the main object otherwise. pub fn link(graph: MachineInstanceGraph) -> Result> { @@ -69,7 +37,7 @@ pub fn link(graph: MachineInstanceGraph) -> Result> { pil.push(PilStatement::Namespace( SourceRef::unknown(), SymbolPath::from_identifier(location.to_string()), - Some(to_namespace_degree(degree)), + Some(degree), )); pil.extend(object.pil); @@ -240,7 +208,7 @@ mod test { use pretty_assertions::assert_eq; - use crate::{link, MAX_DEGREE_LOG, MIN_DEGREE_LOG}; + use crate::link; fn parse_analyze_and_compile_file(file: &str) -> MachineInstanceGraph { let contents = fs::read_to_string(file).unwrap(); @@ -304,13 +272,7 @@ namespace main__rom(4 + 4); #[test] fn compile_really_empty_vm() { - let expectation = format!( - r#"namespace main({}..{}); -"#, - 1 << MIN_DEGREE_LOG, - 1 << *MAX_DEGREE_LOG - ); - + let expectation = "namespace main(0);\n"; let graph = parse_analyze_and_compile::(""); let pil = link(graph).unwrap(); assert_eq!(extract_main(&format!("{pil}")), expectation); diff --git a/pipeline/tests/asm.rs b/pipeline/tests/asm.rs index 77b9f2f0e9..49e944d027 100644 --- a/pipeline/tests/asm.rs +++ b/pipeline/tests/asm.rs @@ -767,7 +767,7 @@ fn types_in_expressions() { O::A(x) => x, } = 0 }; - machine Main { + machine Main with degree: 64 { col witness w; f(); } diff --git a/pipeline/tests/powdr_std.rs b/pipeline/tests/powdr_std.rs index 0168db72d1..9b58d67181 100644 --- a/pipeline/tests/powdr_std.rs +++ b/pipeline/tests/powdr_std.rs @@ -413,7 +413,7 @@ fn sort() { vec![8, 0, 9, 20, 23, 88, 14, -9], ]; let code = - "let test_sort: int[] -> int[] = |x| std::array::sort(x, |a, b| a < b); machine Main { }" + "let test_sort: int[] -> int[] = |x| std::array::sort(x, |a, b| a < b); machine Main with degree: 1024 { }" .to_string(); let mut pipeline = Pipeline::::default().from_asm_string(code, None); let analyzed = pipeline.compute_analyzed_pil().unwrap().clone(); diff --git a/riscv/src/continuations.rs b/riscv/src/continuations.rs index 4dd9fec662..00af82d5ae 100644 --- a/riscv/src/continuations.rs +++ b/riscv/src/continuations.rs @@ -272,7 +272,6 @@ pub fn rust_continuations_dry_run( let length: usize = match max_degree_expr { Some(Expression::Number(_, n)) => n.value.clone().try_into().unwrap(), - // if the max degree is not defined, it defaults to `1 << MAX_DEGREE_LOG` which is too large None => unimplemented!("Continuations rely on `Main` defining a max degree"), Some(e) => { unimplemented!("Continuations rely on `Main` not using a complex expression as its max degree, found {e}") diff --git a/test_data/asm/book/instructions.asm b/test_data/asm/book/instructions.asm index babdc3936e..fa8f32f9f1 100644 --- a/test_data/asm/book/instructions.asm +++ b/test_data/asm/book/instructions.asm @@ -38,7 +38,7 @@ machine Main with degree: 32 { reg C; // ANCHOR: trivial - SubMachine submachine; + SubMachine submachine(32, 32); instr add X, Y -> Z link => Z = submachine.add(X, Y); // - trivial usage: only instruction inputs/outputs used in the call // ANCHOR_END: trivial diff --git a/test_data/asm/book/instructions2.asm b/test_data/asm/book/instructions2.asm index 73f16614e5..189d8d15df 100644 --- a/test_data/asm/book/instructions2.asm +++ b/test_data/asm/book/instructions2.asm @@ -27,7 +27,7 @@ machine Main with degree: 16 { col witness B; col witness C; - SubMachine submachine; + SubMachine submachine(16, 16); // multiple links can be activated by a single instruction, // witness columns can be used for temporary values, diff --git a/test_data/asm/book/modules.asm b/test_data/asm/book/modules.asm index e5ca5f3cde..fe8ce51f44 100644 --- a/test_data/asm/book/modules.asm +++ b/test_data/asm/book/modules.asm @@ -22,16 +22,16 @@ mod utils { machine Main with degree: 8 { // use a machine from another module by relative path - my_module::Other a; + my_module::Other a(8, 8); // use a machine from another module using a local binding - LocalOther b; + LocalOther b(8, 8); // use a machine from another module defined in a different file - SubmoduleOther c; + SubmoduleOther c(8, 8); // use a machine from another module defined in a different directory - FolderSubmoduleOther d; + FolderSubmoduleOther d(8, 8); reg pc[@pc]; diff --git a/test_data/asm/book/operations_and_links.asm b/test_data/asm/book/operations_and_links.asm index 2ddf99203e..804406fe59 100644 --- a/test_data/asm/book/operations_and_links.asm +++ b/test_data/asm/book/operations_and_links.asm @@ -1,5 +1,5 @@ machine Main with degree: 16 { - Add4 adder; + Add4 adder(16, 16); reg pc[@pc]; reg X[<=]; @@ -26,7 +26,7 @@ machine Add4 with latch: latch, operation_id: operation_id { - Add adder; + Add adder(16, 16); operation add4<0> x, y, z, w -> r; diff --git a/test_data/asm/different_signatures.asm b/test_data/asm/different_signatures.asm index 7c15f7b9d1..854739f4dd 100644 --- a/test_data/asm/different_signatures.asm +++ b/test_data/asm/different_signatures.asm @@ -1,5 +1,5 @@ machine Main with degree: 16 { - DifferentSignatures sub; + DifferentSignatures sub(16, 16); reg pc[@pc]; reg X[<=]; diff --git a/test_data/asm/dynamic_vadcop.asm b/test_data/asm/dynamic_vadcop.asm index 6965662348..d012b78713 100644 --- a/test_data/asm/dynamic_vadcop.asm +++ b/test_data/asm/dynamic_vadcop.asm @@ -13,12 +13,14 @@ machine Byte2 with col fixed operation_id = [0]*; } -machine Main { - Arith arith; +let MIN: int = 2**8; +let MAX: int = 2**9; +machine Main with min_degree: MIN, max_degree: MAX { + Arith arith(MIN, MAX); col fixed STEP(i) { i }; Byte2 byte2; - Memory memory(byte2); + Memory memory(byte2, MIN, MAX); reg pc[@pc]; reg X[<=]; diff --git a/test_data/asm/keccakf.asm b/test_data/asm/keccakf.asm index e9a01e7853..f516d61124 100644 --- a/test_data/asm/keccakf.asm +++ b/test_data/asm/keccakf.asm @@ -164,7 +164,9 @@ let main: int, int[], int -> int[] = |W, input, delim| { // main machine machine KeccakF with + degree: 8, latch: LATCH, + degree: 8 { let x; let y; diff --git a/test_data/asm/permutations/binary4.asm b/test_data/asm/permutations/binary4.asm index 9cb74a8c11..e4d2588e76 100644 --- a/test_data/asm/permutations/binary4.asm +++ b/test_data/asm/permutations/binary4.asm @@ -1,6 +1,7 @@ /// Binary machine that works on chunks of 4 bits, /// to be used with permutation lookups. machine Binary4 with + degree: 2**16, latch: latch, operation_id: operation_id, // Allow this machine to be connected via a permutation @@ -34,4 +35,4 @@ machine Binary4 with C' = C * (1 - latch) + C_byte * FACTOR; [A_byte, B_byte, C_byte] in [P_A, P_B, P_C]; -} \ No newline at end of file +} diff --git a/test_data/asm/permutations/block_to_block.asm b/test_data/asm/permutations/block_to_block.asm index 0573713ba5..ccb580287c 100644 --- a/test_data/asm/permutations/block_to_block.asm +++ b/test_data/asm/permutations/block_to_block.asm @@ -6,7 +6,7 @@ machine Binary4x with operation_id: operation_id, call_selectors: sel, { - Binary4 bin; + Binary4 bin(256, 256); operation or4<0> A, B, C, D -> E; @@ -40,8 +40,8 @@ machine Main with degree: 256 { reg A; reg B; - Binary4 bin; - Binary4x bin4; + Binary4 bin(256, 256); + Binary4x bin4(256, 256); // two permutations to machine bin instr or X, Y -> Z link ~> Z = bin.or(X, Y); diff --git a/test_data/asm/permutations/call_selectors_with_no_permutation.asm b/test_data/asm/permutations/call_selectors_with_no_permutation.asm index 1ac23eb27a..9de1c3f238 100644 --- a/test_data/asm/permutations/call_selectors_with_no_permutation.asm +++ b/test_data/asm/permutations/call_selectors_with_no_permutation.asm @@ -8,7 +8,7 @@ machine Main with degree: 128 { reg Z[<=]; reg A; - Binary4 bin; + Binary4 bin(128, 128); // lookup to machine bin instr or X, Y -> Z link => Z = bin.or(X, Y); diff --git a/test_data/asm/permutations/incoming_needs_selector.asm b/test_data/asm/permutations/incoming_needs_selector.asm index 3bad13eb70..55af38e80c 100644 --- a/test_data/asm/permutations/incoming_needs_selector.asm +++ b/test_data/asm/permutations/incoming_needs_selector.asm @@ -19,7 +19,7 @@ machine Main with degree: 32 { reg Z[<=]; reg A; - Binary bin; + Binary bin(32, 32); // permutation into Binary instr add X, Y -> Z link ~> Z = bin.add(X, Y); diff --git a/test_data/asm/permutations/link_merging.asm b/test_data/asm/permutations/link_merging.asm index a0a77174ba..c10154c24d 100644 --- a/test_data/asm/permutations/link_merging.asm +++ b/test_data/asm/permutations/link_merging.asm @@ -25,7 +25,7 @@ machine Main with degree: 32 { reg C; col witness tmp; - SubMachine submachine; + SubMachine submachine(32, 32); // these are merged into 1 link instr add X, Y -> Z link => Z = submachine.add(X, Y); diff --git a/test_data/asm/permutations/simple.asm b/test_data/asm/permutations/simple.asm index 3b2c6b2ead..018cb6a545 100644 --- a/test_data/asm/permutations/simple.asm +++ b/test_data/asm/permutations/simple.asm @@ -8,7 +8,7 @@ machine Main with degree: 128 { reg Z[<=]; reg A; - Binary4 bin; + Binary4 bin(128, 128); // permutation to machine bin instr or X, Y -> Z link ~> Z = bin.or(X, Y); diff --git a/test_data/asm/permutations/vm_to_block.asm b/test_data/asm/permutations/vm_to_block.asm index f300e4a528..2f39b42ff6 100644 --- a/test_data/asm/permutations/vm_to_block.asm +++ b/test_data/asm/permutations/vm_to_block.asm @@ -9,7 +9,7 @@ machine Main with degree: 128 { reg A; reg B; - Binary4 bin; + Binary4 bin(128, 128); // two permutations to machine bin instr or X, Y -> Z link ~> Z = bin.or(X, Y); diff --git a/test_data/asm/permutations/vm_to_vm.asm b/test_data/asm/permutations/vm_to_vm.asm index 12bf55fb1b..5ea18df04f 100644 --- a/test_data/asm/permutations/vm_to_vm.asm +++ b/test_data/asm/permutations/vm_to_vm.asm @@ -23,7 +23,7 @@ machine Main with degree: 32 { reg A; reg B; - Binary bin; + Binary bin(32, 32); // two permutations to bin machine instr add X, Y -> Z link ~> Z = bin.add(X, Y); diff --git a/test_data/std/add_sub_small_test.asm b/test_data/std/add_sub_small_test.asm index 36941827a5..dc2a583ba8 100644 --- a/test_data/std/add_sub_small_test.asm +++ b/test_data/std/add_sub_small_test.asm @@ -1,7 +1,7 @@ use std::machines::small_field::add_sub::AddSub; use std::machines::range::Byte2; -machine Main { +machine Main with degree: 2**12 { reg pc[@pc]; reg A_h[<=]; reg A_l[<=]; diff --git a/test_data/std/binary_small_8_test.asm b/test_data/std/binary_small_8_test.asm index d3213b4ecc..597efff870 100644 --- a/test_data/std/binary_small_8_test.asm +++ b/test_data/std/binary_small_8_test.asm @@ -1,7 +1,7 @@ use std::machines::binary::ByteBinary; use std::machines::small_field::binary::Binary8; -machine Main { +machine Main with degree: 2**18 { reg pc[@pc]; reg X0_1[<=]; reg X0_2[<=]; diff --git a/test_data/std/binary_small_test.asm b/test_data/std/binary_small_test.asm index c103c440fe..c0077476bb 100644 --- a/test_data/std/binary_small_test.asm +++ b/test_data/std/binary_small_test.asm @@ -1,7 +1,7 @@ use std::machines::binary::ByteBinary; use std::machines::small_field::binary::Binary; -machine Main { +machine Main with degree: 2**18 { reg pc[@pc]; reg X0_1[<=]; reg X0_2[<=];