diff --git a/vm/src/chips/chips/alu/add_sub/mod.rs b/vm/src/chips/chips/alu/add_sub/mod.rs index 4fa28450..03c2143c 100644 --- a/vm/src/chips/chips/alu/add_sub/mod.rs +++ b/vm/src/chips/chips/alu/add_sub/mod.rs @@ -4,6 +4,9 @@ pub mod columns; pub mod constraints; pub mod traces; +#[cfg(test)] +mod tests; + /// A chip that implements addition for the opcode ADD and SUB. /// /// SUB is basically an ADD with a re-arrangment of the operands and result. diff --git a/vm/src/chips/chips/alu/add_sub/tests.rs b/vm/src/chips/chips/alu/add_sub/tests.rs new file mode 100644 index 00000000..63792d81 --- /dev/null +++ b/vm/src/chips/chips/alu/add_sub/tests.rs @@ -0,0 +1,29 @@ +use super::AddSubChip; +use crate::machine::{chip::ChipBehavior, folder::SymbolicConstraintFolder}; +use p3_air::{Air, BaseAir}; +use p3_koala_bear::KoalaBear; + +#[test] +fn test_add_sub_chip_simple_eval() { + // crate a add-sub chip + let chip: AddSubChip = AddSubChip::default(); + + // get the preprocessed and main trace widths + let preprocessed_width = chip.preprocessed_width(); + let width = chip.width(); + + // create a constraint builder and evaluate with the chip + let mut builder = SymbolicConstraintFolder::new(preprocessed_width, width); + chip.eval(&mut builder); + + // check the constraints and public values + assert_eq!(builder.constraints.len(), 17); + assert_eq!(builder.public_values.len(), 231); + + // check the looking (sending) and looked (receiving) lookups + let (looking, looked) = builder.lookups(); + assert_eq!(looking.len(), 6); + assert_eq!(looked.len(), 2); + + // TODO: check the details of evaluated result +} diff --git a/vm/src/chips/chips/alu/bitwise/mod.rs b/vm/src/chips/chips/alu/bitwise/mod.rs index 4cd1ffe0..659182d0 100644 --- a/vm/src/chips/chips/alu/bitwise/mod.rs +++ b/vm/src/chips/chips/alu/bitwise/mod.rs @@ -4,6 +4,9 @@ pub mod columns; pub mod constraints; pub mod traces; +#[cfg(test)] +mod tests; + /// A chip that implements bitwise operations for the opcodes XOR, OR, and AND. #[derive(Default)] pub struct BitwiseChip(PhantomData); diff --git a/vm/src/chips/chips/alu/bitwise/tests.rs b/vm/src/chips/chips/alu/bitwise/tests.rs new file mode 100644 index 00000000..8eab00e1 --- /dev/null +++ b/vm/src/chips/chips/alu/bitwise/tests.rs @@ -0,0 +1,29 @@ +use super::BitwiseChip; +use crate::machine::{chip::ChipBehavior, folder::SymbolicConstraintFolder}; +use p3_air::{Air, BaseAir}; +use p3_koala_bear::KoalaBear; + +#[test] +fn test_bitwise_chip_simple_eval() { + // crate a bitwise chip + let chip: BitwiseChip = BitwiseChip::default(); + + // get the preprocessed and main trace widths + let preprocessed_width = chip.preprocessed_width(); + let width = chip.width(); + + // create a constraint builder and evaluate with the chip + let mut builder = SymbolicConstraintFolder::new(preprocessed_width, width); + chip.eval(&mut builder); + + // check the constraints and public values + assert_eq!(builder.constraints.len(), 4); + assert_eq!(builder.public_values.len(), 231); + + // check the looking (sending) and looked (receiving) lookups + let (looking, looked) = builder.lookups(); + assert_eq!(looking.len(), 4); + assert_eq!(looked.len(), 1); + + // TODO: check the details of evaluated result +} diff --git a/vm/src/chips/chips/alu/divrem/mod.rs b/vm/src/chips/chips/alu/divrem/mod.rs index 8a7bf162..96a1fa8b 100644 --- a/vm/src/chips/chips/alu/divrem/mod.rs +++ b/vm/src/chips/chips/alu/divrem/mod.rs @@ -5,6 +5,9 @@ pub mod constraints; pub mod traces; mod utils; +#[cfg(test)] +mod tests; + /// A chip that implements addition for the opcodes DIV/REM. #[derive(Default)] pub struct DivRemChip(PhantomData); diff --git a/vm/src/chips/chips/alu/divrem/tests.rs b/vm/src/chips/chips/alu/divrem/tests.rs new file mode 100644 index 00000000..bba10e94 --- /dev/null +++ b/vm/src/chips/chips/alu/divrem/tests.rs @@ -0,0 +1,29 @@ +use super::DivRemChip; +use crate::machine::{chip::ChipBehavior, folder::SymbolicConstraintFolder}; +use p3_air::{Air, BaseAir}; +use p3_koala_bear::KoalaBear; + +#[test] +fn test_div_rem_chip_simple_eval() { + // crate a divrem chip + let chip: DivRemChip = DivRemChip::default(); + + // get the preprocessed and main trace widths + let preprocessed_width = chip.preprocessed_width(); + let width = chip.width(); + + // create a constraint builder and evaluate with the chip + let mut builder = SymbolicConstraintFolder::new(preprocessed_width, width); + chip.eval(&mut builder); + + // check the constraints and public values + assert_eq!(builder.constraints.len(), 131); + assert_eq!(builder.public_values.len(), 231); + + // check the looking (sending) and looked (receiving) lookups + let (looking, looked) = builder.lookups(); + assert_eq!(looking.len(), 16); + assert_eq!(looked.len(), 1); + + // TODO: check the details of evaluated result +} diff --git a/vm/src/chips/chips/alu/lt/mod.rs b/vm/src/chips/chips/alu/lt/mod.rs index 055151bb..5c545ab3 100644 --- a/vm/src/chips/chips/alu/lt/mod.rs +++ b/vm/src/chips/chips/alu/lt/mod.rs @@ -2,5 +2,8 @@ mod columns; mod constraints; mod traces; +#[cfg(test)] +mod tests; + pub use columns::*; pub use traces::*; diff --git a/vm/src/chips/chips/alu/lt/tests.rs b/vm/src/chips/chips/alu/lt/tests.rs new file mode 100644 index 00000000..94f16552 --- /dev/null +++ b/vm/src/chips/chips/alu/lt/tests.rs @@ -0,0 +1,29 @@ +use super::LtChip; +use crate::machine::{chip::ChipBehavior, folder::SymbolicConstraintFolder}; +use p3_air::{Air, BaseAir}; +use p3_koala_bear::KoalaBear; + +#[test] +fn test_lt_chip_simple_eval() { + // crate a less-than chip + let chip: LtChip = LtChip::default(); + + // get the preprocessed and main trace widths + let preprocessed_width = chip.preprocessed_width(); + let width = chip.width(); + + // create a constraint builder and evaluate with the chip + let mut builder = SymbolicConstraintFolder::new(preprocessed_width, width); + chip.eval(&mut builder); + + // check the constraints and public values + assert_eq!(builder.constraints.len(), 32); + assert_eq!(builder.public_values.len(), 231); + + // check the looking (sending) and looked (receiving) lookups + let (looking, looked) = builder.lookups(); + assert_eq!(looking.len(), 3); + assert_eq!(looked.len(), 1); + + // TODO: check the details of evaluated result +} diff --git a/vm/src/chips/chips/alu/mul/mod.rs b/vm/src/chips/chips/alu/mul/mod.rs index 808f55c7..90031ae2 100644 --- a/vm/src/chips/chips/alu/mul/mod.rs +++ b/vm/src/chips/chips/alu/mul/mod.rs @@ -6,6 +6,9 @@ pub mod columns; pub mod constraints; pub mod traces; +#[cfg(test)] +mod tests; + /// The number of digits in the product is at most the sum of the number of digits in the /// multiplicands. const PRODUCT_SIZE: usize = 2 * WORD_SIZE; diff --git a/vm/src/chips/chips/alu/mul/tests.rs b/vm/src/chips/chips/alu/mul/tests.rs new file mode 100644 index 00000000..06e7c85c --- /dev/null +++ b/vm/src/chips/chips/alu/mul/tests.rs @@ -0,0 +1,29 @@ +use super::MulChip; +use crate::machine::{chip::ChipBehavior, folder::SymbolicConstraintFolder}; +use p3_air::{Air, BaseAir}; +use p3_koala_bear::KoalaBear; + +#[test] +fn test_mul_chip_simple_eval() { + // crate a mul chip + let chip: MulChip = MulChip::default(); + + // get the preprocessed and main trace widths + let preprocessed_width = chip.preprocessed_width(); + let width = chip.width(); + + // create a constraint builder and evaluate with the chip + let mut builder = SymbolicConstraintFolder::new(preprocessed_width, width); + chip.eval(&mut builder); + + // check the constraints and public values + assert_eq!(builder.constraints.len(), 30); + assert_eq!(builder.public_values.len(), 231); + + // check the looking (sending) and looked (receiving) lookups + let (looking, looked) = builder.lookups(); + assert_eq!(looking.len(), 14); + assert_eq!(looked.len(), 1); + + // TODO: check the details of evaluated result +} diff --git a/vm/src/chips/chips/alu/sll/mod.rs b/vm/src/chips/chips/alu/sll/mod.rs index 055151bb..5c545ab3 100644 --- a/vm/src/chips/chips/alu/sll/mod.rs +++ b/vm/src/chips/chips/alu/sll/mod.rs @@ -2,5 +2,8 @@ mod columns; mod constraints; mod traces; +#[cfg(test)] +mod tests; + pub use columns::*; pub use traces::*; diff --git a/vm/src/chips/chips/alu/sll/tests.rs b/vm/src/chips/chips/alu/sll/tests.rs new file mode 100644 index 00000000..4cc41706 --- /dev/null +++ b/vm/src/chips/chips/alu/sll/tests.rs @@ -0,0 +1,29 @@ +use super::SLLChip; +use crate::machine::{chip::ChipBehavior, folder::SymbolicConstraintFolder}; +use p3_air::{Air, BaseAir}; +use p3_koala_bear::KoalaBear; + +#[test] +fn test_shift_left_chip_simple_eval() { + // crate a shift-left chip + let chip: SLLChip = SLLChip::default(); + + // get the preprocessed and main trace widths + let preprocessed_width = chip.preprocessed_width(); + let width = chip.width(); + + // create a constraint builder and evaluate with the chip + let mut builder = SymbolicConstraintFolder::new(preprocessed_width, width); + chip.eval(&mut builder); + + // check the constraints and public values + assert_eq!(builder.constraints.len(), 64); + assert_eq!(builder.public_values.len(), 231); + + // check the looking (sending) and looked (receiving) lookups + let (looking, looked) = builder.lookups(); + assert_eq!(looking.len(), 4); + assert_eq!(looked.len(), 1); + + // TODO: check the details of evaluated result +} diff --git a/vm/src/chips/chips/alu/sr/mod.rs b/vm/src/chips/chips/alu/sr/mod.rs index 6b97216d..6bc250be 100644 --- a/vm/src/chips/chips/alu/sr/mod.rs +++ b/vm/src/chips/chips/alu/sr/mod.rs @@ -1,3 +1,6 @@ pub mod columns; pub mod constraints; pub mod traces; + +#[cfg(test)] +mod tests; diff --git a/vm/src/chips/chips/alu/sr/tests.rs b/vm/src/chips/chips/alu/sr/tests.rs new file mode 100644 index 00000000..3887c547 --- /dev/null +++ b/vm/src/chips/chips/alu/sr/tests.rs @@ -0,0 +1,29 @@ +use super::traces::ShiftRightChip; +use crate::machine::{chip::ChipBehavior, folder::SymbolicConstraintFolder}; +use p3_air::{Air, BaseAir}; +use p3_koala_bear::KoalaBear; + +#[test] +fn test_shift_right_chip_simple_eval() { + // crate a shift-right chip + let chip: ShiftRightChip = ShiftRightChip::default(); + + // get the preprocessed and main trace widths + let preprocessed_width = chip.preprocessed_width(); + let width = chip.width(); + + // create a constraint builder and evaluate with the chip + let mut builder = SymbolicConstraintFolder::new(preprocessed_width, width); + chip.eval(&mut builder); + + // check the constraints and public values + assert_eq!(builder.constraints.len(), 81); + assert_eq!(builder.public_values.len(), 231); + + // check the looking (sending) and looked (receiving) lookups + let (looking, looked) = builder.lookups(); + assert_eq!(looking.len(), 25); + assert_eq!(looked.len(), 1); + + // TODO: check the details of evaluated result +} diff --git a/vm/src/chips/chips/riscv_cpu/auipc/mod.rs b/vm/src/chips/chips/riscv_cpu/auipc/mod.rs index 6b97216d..6bc250be 100644 --- a/vm/src/chips/chips/riscv_cpu/auipc/mod.rs +++ b/vm/src/chips/chips/riscv_cpu/auipc/mod.rs @@ -1,3 +1,6 @@ pub mod columns; pub mod constraints; pub mod traces; + +#[cfg(test)] +mod tests; diff --git a/vm/src/chips/chips/riscv_cpu/auipc/tests.rs b/vm/src/chips/chips/riscv_cpu/auipc/tests.rs new file mode 100644 index 00000000..924bd709 --- /dev/null +++ b/vm/src/chips/chips/riscv_cpu/auipc/tests.rs @@ -0,0 +1,36 @@ +use crate::{ + chips::chips::riscv_cpu::{columns::CpuCols, CpuChip}, + machine::{chip::ChipBehavior, folder::SymbolicConstraintFolder}, +}; +use p3_air::{AirBuilder, BaseAir}; +use p3_koala_bear::KoalaBear; +use p3_matrix::Matrix; +use std::borrow::Borrow; + +#[test] +fn test_auipc_instruction_simple_eval() { + // crate a riscv-cpu chip + let chip: CpuChip = CpuChip::default(); + + // get the preprocessed and main trace widths + let preprocessed_width = chip.preprocessed_width(); + let width = chip.width(); + + // create a constraint builder and evaluate with the chip + let mut builder = SymbolicConstraintFolder::new(preprocessed_width, width); + let main = builder.main(); + let local = main.row_slice(0); + let local: &CpuCols<_> = (*local).borrow(); + + // evaluate auipc instruction + chip.eval_auipc(&mut builder, local); + + // check the constraints and public values + assert_eq!(builder.constraints.len(), 16); + assert_eq!(builder.public_values.len(), 231); + + // check the looking (sending) and looked (receiving) lookups + let (looking, looked) = builder.lookups(); + assert_eq!(looking.len(), 1); + assert_eq!(looked.len(), 0); +} diff --git a/vm/src/chips/chips/riscv_cpu/branch/mod.rs b/vm/src/chips/chips/riscv_cpu/branch/mod.rs index 6b97216d..6bc250be 100644 --- a/vm/src/chips/chips/riscv_cpu/branch/mod.rs +++ b/vm/src/chips/chips/riscv_cpu/branch/mod.rs @@ -1,3 +1,6 @@ pub mod columns; pub mod constraints; pub mod traces; + +#[cfg(test)] +mod tests; diff --git a/vm/src/chips/chips/riscv_cpu/branch/tests.rs b/vm/src/chips/chips/riscv_cpu/branch/tests.rs new file mode 100644 index 00000000..b285227c --- /dev/null +++ b/vm/src/chips/chips/riscv_cpu/branch/tests.rs @@ -0,0 +1,38 @@ +use crate::{ + chips::chips::riscv_cpu::{columns::CpuCols, CpuChip}, + machine::{chip::ChipBehavior, folder::SymbolicConstraintFolder}, +}; +use p3_air::{AirBuilder, BaseAir}; +use p3_field::FieldAlgebra; +use p3_koala_bear::KoalaBear; +use p3_matrix::Matrix; +use std::borrow::Borrow; + +#[test] +fn test_branch_instruction_simple_eval() { + // crate a riscv-cpu chip + let chip: CpuChip = CpuChip::default(); + + // get the preprocessed and main trace widths + let preprocessed_width = chip.preprocessed_width(); + let width = chip.width(); + + // create a constraint builder and evaluate with the chip + let mut builder = SymbolicConstraintFolder::new(preprocessed_width, width); + let main = builder.main(); + let (local, next) = (main.row_slice(0), main.row_slice(1)); + let local: &CpuCols<_> = (*local).borrow(); + let next: &CpuCols<_> = (*next).borrow(); + + // evaluate branch instruction + chip.eval_branch_ops(&mut builder, KoalaBear::ONE.into(), local, next); + + // check the constraints and public values + assert_eq!(builder.constraints.len(), 52); + assert_eq!(builder.public_values.len(), 231); + + // check the looking (sending) and looked (receiving) lookups + let (looking, looked) = builder.lookups(); + assert_eq!(looking.len(), 3); + assert_eq!(looked.len(), 0); +} diff --git a/vm/src/chips/chips/riscv_cpu/jump/mod.rs b/vm/src/chips/chips/riscv_cpu/jump/mod.rs index 6b97216d..6bc250be 100644 --- a/vm/src/chips/chips/riscv_cpu/jump/mod.rs +++ b/vm/src/chips/chips/riscv_cpu/jump/mod.rs @@ -1,3 +1,6 @@ pub mod columns; pub mod constraints; pub mod traces; + +#[cfg(test)] +mod tests; diff --git a/vm/src/chips/chips/riscv_cpu/jump/tests.rs b/vm/src/chips/chips/riscv_cpu/jump/tests.rs new file mode 100644 index 00000000..301d4c44 --- /dev/null +++ b/vm/src/chips/chips/riscv_cpu/jump/tests.rs @@ -0,0 +1,37 @@ +use crate::{ + chips::chips::riscv_cpu::{columns::CpuCols, CpuChip}, + machine::{chip::ChipBehavior, folder::SymbolicConstraintFolder}, +}; +use p3_air::{AirBuilder, BaseAir}; +use p3_koala_bear::KoalaBear; +use p3_matrix::Matrix; +use std::borrow::Borrow; + +#[test] +fn test_jump_instruction_simple_eval() { + // crate a riscv-cpu chip + let chip: CpuChip = CpuChip::default(); + + // get the preprocessed and main trace widths + let preprocessed_width = chip.preprocessed_width(); + let width = chip.width(); + + // create a constraint builder and evaluate with the chip + let mut builder = SymbolicConstraintFolder::new(preprocessed_width, width); + let main = builder.main(); + let (local, next) = (main.row_slice(0), main.row_slice(1)); + let local: &CpuCols<_> = (*local).borrow(); + let next: &CpuCols<_> = (*next).borrow(); + + // evaluate jump instruction + chip.eval_jump_ops(&mut builder, local, next); + + // check the constraints and public values + assert_eq!(builder.constraints.len(), 49); + assert_eq!(builder.public_values.len(), 231); + + // check the looking (sending) and looked (receiving) lookups + let (looking, looked) = builder.lookups(); + assert_eq!(looking.len(), 2); + assert_eq!(looked.len(), 0); +} diff --git a/vm/src/chips/chips/riscv_cpu/mod.rs b/vm/src/chips/chips/riscv_cpu/mod.rs index 2c37bedb..cedb8fbe 100644 --- a/vm/src/chips/chips/riscv_cpu/mod.rs +++ b/vm/src/chips/chips/riscv_cpu/mod.rs @@ -16,5 +16,8 @@ pub mod register; pub mod traces; pub mod utils; +#[cfg(test)] +mod tests; + #[derive(Default)] pub struct CpuChip(PhantomData); diff --git a/vm/src/chips/chips/riscv_cpu/tests.rs b/vm/src/chips/chips/riscv_cpu/tests.rs new file mode 100644 index 00000000..22949bc8 --- /dev/null +++ b/vm/src/chips/chips/riscv_cpu/tests.rs @@ -0,0 +1,29 @@ +use super::CpuChip; +use crate::machine::{chip::ChipBehavior, folder::SymbolicConstraintFolder}; +use p3_air::{Air, BaseAir}; +use p3_koala_bear::KoalaBear; + +#[test] +fn test_riscv_cpu_chip_simple_eval() { + // crate a riscv-cpu chip + let chip: CpuChip = CpuChip::default(); + + // get the preprocessed and main trace widths + let preprocessed_width = chip.preprocessed_width(); + let width = chip.width(); + + // create a constraint builder and evaluate with the chip + let mut builder = SymbolicConstraintFolder::new(preprocessed_width, width); + chip.eval(&mut builder); + + // check the constraints and public values + assert_eq!(builder.constraints.len(), 261); + assert_eq!(builder.public_values.len(), 231); + + // check the looking (sending) and looked (receiving) lookups + let (looking, looked) = builder.lookups(); + assert_eq!(looking.len(), 24); + assert_eq!(looked.len(), 3); + + // TODO: check the details of evaluated result +} diff --git a/vm/src/chips/chips/riscv_global/mod.rs b/vm/src/chips/chips/riscv_global/mod.rs index 9924677d..387e4c22 100644 --- a/vm/src/chips/chips/riscv_global/mod.rs +++ b/vm/src/chips/chips/riscv_global/mod.rs @@ -5,5 +5,8 @@ pub mod constraints; pub mod event; pub mod traces; +#[cfg(test)] +mod tests; + #[derive(Default)] pub struct GlobalChip(PhantomData); diff --git a/vm/src/chips/chips/riscv_global/tests.rs b/vm/src/chips/chips/riscv_global/tests.rs new file mode 100644 index 00000000..c7e48df0 --- /dev/null +++ b/vm/src/chips/chips/riscv_global/tests.rs @@ -0,0 +1,27 @@ +use super::GlobalChip; +use crate::machine::{chip::ChipBehavior, folder::SymbolicConstraintFolder}; +use p3_air::{Air, BaseAir}; +use p3_koala_bear::KoalaBear; + +#[test] +fn test_riscv_global_chip_simple_eval() { + // crate a riscv global chip + let chip: GlobalChip = GlobalChip::default(); + + // get the preprocessed and main trace widths + let preprocessed_width = chip.preprocessed_width(); + let width = chip.width(); + + // create a constraint builder and evaluate with the chip + let mut builder = SymbolicConstraintFolder::new(preprocessed_width, width); + chip.eval(&mut builder); + + // check the constraints and public values + assert_eq!(builder.constraints.len(), 137); + assert_eq!(builder.public_values.len(), 231); + + // check the looking (sending) and looked (receiving) lookups + let (looking, looked) = builder.lookups(); + assert_eq!(looking.len(), 2); + assert_eq!(looked.len(), 1); +} diff --git a/vm/src/chips/chips/riscv_memory/read_write/mod.rs b/vm/src/chips/chips/riscv_memory/read_write/mod.rs index 297db502..94f62d1d 100644 --- a/vm/src/chips/chips/riscv_memory/read_write/mod.rs +++ b/vm/src/chips/chips/riscv_memory/read_write/mod.rs @@ -4,6 +4,9 @@ pub mod columns; pub mod constraints; pub mod traces; +#[cfg(test)] +mod tests; + /// A chip for memory read and write #[derive(Default)] pub struct MemoryReadWriteChip(PhantomData); diff --git a/vm/src/chips/chips/riscv_memory/read_write/tests.rs b/vm/src/chips/chips/riscv_memory/read_write/tests.rs new file mode 100644 index 00000000..a9b55d8a --- /dev/null +++ b/vm/src/chips/chips/riscv_memory/read_write/tests.rs @@ -0,0 +1,29 @@ +use super::MemoryReadWriteChip; +use crate::machine::{chip::ChipBehavior, folder::SymbolicConstraintFolder}; +use p3_air::{Air, BaseAir}; +use p3_koala_bear::KoalaBear; + +#[test] +fn test_riscv_memory_read_write_chip_simple_eval() { + // crate a riscv-memory-read-write chip + let chip: MemoryReadWriteChip = MemoryReadWriteChip::default(); + + // get the preprocessed and main trace widths + let preprocessed_width = chip.preprocessed_width(); + let width = chip.width(); + + // create a constraint builder and evaluate with the chip + let mut builder = SymbolicConstraintFolder::new(preprocessed_width, width); + chip.eval(&mut builder); + + // check the constraints and public values + assert_eq!(builder.constraints.len(), 92); + assert_eq!(builder.public_values.len(), 231); + + // check the looking (sending) and looked (receiving) lookups + let (looking, looked) = builder.lookups(); + assert_eq!(looking.len(), 7); + assert_eq!(looked.len(), 2); + + // TODO: check the details of evaluated result +} diff --git a/vm/src/chips/chips/riscv_program/mod.rs b/vm/src/chips/chips/riscv_program/mod.rs index bb530a84..bc3f4d1b 100644 --- a/vm/src/chips/chips/riscv_program/mod.rs +++ b/vm/src/chips/chips/riscv_program/mod.rs @@ -4,6 +4,9 @@ pub mod columns; pub mod constraints; pub mod traces; +#[cfg(test)] +mod tests; + /// A chip that implements addition for the opcodes ADD and ADDI. #[derive(Default)] pub struct ProgramChip(PhantomData); diff --git a/vm/src/chips/chips/riscv_program/tests.rs b/vm/src/chips/chips/riscv_program/tests.rs new file mode 100644 index 00000000..b4044447 --- /dev/null +++ b/vm/src/chips/chips/riscv_program/tests.rs @@ -0,0 +1,28 @@ +use super::ProgramChip; +use crate::machine::{chip::ChipBehavior, folder::SymbolicConstraintFolder}; +use p3_air::{Air, BaseAir}; +use p3_koala_bear::KoalaBear; + +#[test] +fn test_riscv_program_chip_simple_eval() { + // crate a riscv program chip + let chip: ProgramChip = ProgramChip::default(); + + // get the preprocessed and main trace widths + let preprocessed_width = chip.preprocessed_width(); + let width = chip.width(); + + // create a constraint builder and evaluate with the chip + let mut builder = SymbolicConstraintFolder::new(preprocessed_width, width); + chip.eval(&mut builder); + + // check the constraints and public values + // no constraints and only has lookups + assert_eq!(builder.constraints.len(), 0); + assert_eq!(builder.public_values.len(), 231); + + // check the looking (sending) and looked (receiving) lookups + let (looking, looked) = builder.lookups(); + assert_eq!(looking.len(), 0); + assert_eq!(looked.len(), 1); +} diff --git a/vm/src/chips/gadgets/add.rs b/vm/src/chips/gadgets/add.rs index d09af0b3..00344f78 100644 --- a/vm/src/chips/gadgets/add.rs +++ b/vm/src/chips/gadgets/add.rs @@ -108,3 +108,37 @@ impl AddGadget { } } } + +#[cfg(test)] +mod tests { + use super::*; + use crate::machine::folder::SymbolicConstraintFolder; + use p3_koala_bear::KoalaBear; + use p3_uni_stark::{Entry, SymbolicVariable}; + + #[test] + fn test_add_gadget_simple_eval() { + let var = SymbolicVariable::new(Entry::Main { offset: 0 }, 0); + let word = Word([var; 4]); + + // create a new gadget + let gadget = AddGadget { + value: word, + carry: [var; 3], + }; + // create a constraint builder + let mut builder = SymbolicConstraintFolder::new(0, size_of::>()); + + // evaluate with this gadget + AddGadget::::eval(&mut builder, word, word, gadget, Default::default()); + + // check the constraints and public values + assert_eq!(builder.constraints.len(), 14); + assert_eq!(builder.public_values.len(), 231); + + // check the looking (sending) and looked (receiving) lookups + let (looking, looked) = builder.lookups(); + assert_eq!(looking.len(), 6); + assert_eq!(looked.len(), 0); + } +} diff --git a/vm/src/chips/gadgets/add4.rs b/vm/src/chips/gadgets/add4.rs index b8d08a4e..610b4727 100644 --- a/vm/src/chips/gadgets/add4.rs +++ b/vm/src/chips/gadgets/add4.rs @@ -150,3 +150,41 @@ impl Add4Operation { } } } + +#[cfg(test)] +mod tests { + use super::*; + use crate::machine::folder::SymbolicConstraintFolder; + use p3_koala_bear::KoalaBear; + use p3_uni_stark::{Entry, SymbolicVariable}; + + #[test] + fn test_add4_gadget_simple_eval() { + let var = SymbolicVariable::new(Entry::Main { offset: 0 }, 0); + let word = Word([var; 4]); + + // create a new gadget + let gadget = Add4Operation { + value: word, + is_carry_0: word, + is_carry_1: word, + is_carry_2: word, + is_carry_3: word, + carry: word, + }; + // create a constraint builder + let mut builder = SymbolicConstraintFolder::new(0, size_of::>()); + + // evaluate with this gadget + Add4Operation::::eval(&mut builder, word, word, word, word, var, gadget); + + // check the constraints and public values + assert_eq!(builder.constraints.len(), 29); + assert_eq!(builder.public_values.len(), 231); + + // check the looking (sending) and looked (receiving) lookups + let (looking, looked) = builder.lookups(); + assert_eq!(looking.len(), 10); + assert_eq!(looked.len(), 0); + } +} diff --git a/vm/src/chips/gadgets/add5.rs b/vm/src/chips/gadgets/add5.rs index a7f8d077..f5729bcc 100644 --- a/vm/src/chips/gadgets/add5.rs +++ b/vm/src/chips/gadgets/add5.rs @@ -160,3 +160,47 @@ impl Add5Operation { } } } + +#[cfg(test)] +mod tests { + use super::*; + use crate::machine::folder::SymbolicConstraintFolder; + use p3_koala_bear::KoalaBear; + use p3_uni_stark::{Entry, SymbolicVariable}; + + #[test] + fn test_add5_gadget_simple_eval() { + let var = SymbolicVariable::new(Entry::Main { offset: 0 }, 0); + let word = Word([var; 4]); + + // create a new gadget + let gadget = Add5Operation { + value: word, + is_carry_0: word, + is_carry_1: word, + is_carry_2: word, + is_carry_3: word, + is_carry_4: word, + carry: word, + }; + // create a constraint builder + let mut builder = SymbolicConstraintFolder::new(0, size_of::>()); + + // evaluate with this gadget + Add5Operation::::eval( + &mut builder, + &[word, word, word, word, word], + var, + gadget, + ); + + // check the constraints and public values + assert_eq!(builder.constraints.len(), 33); + assert_eq!(builder.public_values.len(), 231); + + // check the looking (sending) and looked (receiving) lookups + let (looking, looked) = builder.lookups(); + assert_eq!(looking.len(), 12); + assert_eq!(looked.len(), 0); + } +} diff --git a/vm/src/chips/gadgets/and.rs b/vm/src/chips/gadgets/and.rs index bc698f93..756854a6 100644 --- a/vm/src/chips/gadgets/and.rs +++ b/vm/src/chips/gadgets/and.rs @@ -55,3 +55,34 @@ impl AndOperation { } } } + +#[cfg(test)] +mod tests { + use super::*; + use crate::machine::folder::SymbolicConstraintFolder; + use p3_koala_bear::KoalaBear; + use p3_uni_stark::{Entry, SymbolicVariable}; + + #[test] + fn test_and_gadget_simple_eval() { + let var = SymbolicVariable::new(Entry::Main { offset: 0 }, 0); + let word = Word([var; 4]); + + // create a new gadget + let gadget = AndOperation { value: word }; + // create a constraint builder + let mut builder = SymbolicConstraintFolder::new(0, size_of::>()); + + // evaluate with this gadget + AndOperation::::eval(&mut builder, word, word, gadget, var); + + // check the constraints and public values + assert_eq!(builder.constraints.len(), 0); + assert_eq!(builder.public_values.len(), 231); + + // check the looking (sending) and looked (receiving) lookups + let (looking, looked) = builder.lookups(); + assert_eq!(looking.len(), 4); + assert_eq!(looked.len(), 0); + } +} diff --git a/vm/src/chips/gadgets/fixed_rotate_right.rs b/vm/src/chips/gadgets/fixed_rotate_right.rs index b110c0ee..c7e94c82 100644 --- a/vm/src/chips/gadgets/fixed_rotate_right.rs +++ b/vm/src/chips/gadgets/fixed_rotate_right.rs @@ -152,3 +152,39 @@ impl FixedRotateRightOperation { ); } } + +#[cfg(test)] +mod tests { + use super::*; + use crate::machine::folder::SymbolicConstraintFolder; + use p3_koala_bear::KoalaBear; + use p3_uni_stark::{Entry, SymbolicVariable}; + + #[test] + fn test_fixed_rotate_right_gadget_simple_eval() { + let var = SymbolicVariable::new(Entry::Main { offset: 0 }, 0); + let word = Word([var; 4]); + + // create a new gadget + let gadget = FixedRotateRightOperation { + value: word, + shift: word, + carry: word, + }; + // create a constraint builder + let mut builder = + SymbolicConstraintFolder::new(0, size_of::>()); + + // evaluate with this gadget + FixedRotateRightOperation::::eval(&mut builder, word, 1, gadget, var); + + // check the constraints and public values + assert_eq!(builder.constraints.len(), 4); + assert_eq!(builder.public_values.len(), 231); + + // check the looking (sending) and looked (receiving) lookups + let (looking, looked) = builder.lookups(); + assert_eq!(looking.len(), 4); + assert_eq!(looked.len(), 0); + } +} diff --git a/vm/src/chips/gadgets/fixed_shift_right.rs b/vm/src/chips/gadgets/fixed_shift_right.rs index 6638fdc4..8484bdf5 100644 --- a/vm/src/chips/gadgets/fixed_shift_right.rs +++ b/vm/src/chips/gadgets/fixed_shift_right.rs @@ -149,3 +149,39 @@ impl FixedShiftRightOperation { builder.assert_eq(cols.value[WORD_SIZE - 1], first_shift); } } + +#[cfg(test)] +mod tests { + use super::*; + use crate::machine::folder::SymbolicConstraintFolder; + use p3_koala_bear::KoalaBear; + use p3_uni_stark::{Entry, SymbolicVariable}; + + #[test] + fn test_fixed_shift_right_gadget_simple_eval() { + let var = SymbolicVariable::new(Entry::Main { offset: 0 }, 0); + let word = Word([var; 4]); + + // create a new gadget + let gadget = FixedShiftRightOperation { + value: word, + shift: word, + carry: word, + }; + // create a constraint builder + let mut builder = + SymbolicConstraintFolder::new(0, size_of::>()); + + // evaluate with this gadget + FixedShiftRightOperation::::eval(&mut builder, word, 1, gadget, var); + + // check the constraints and public values + assert_eq!(builder.constraints.len(), 4); + assert_eq!(builder.public_values.len(), 231); + + // check the looking (sending) and looked (receiving) lookups + let (looking, looked) = builder.lookups(); + assert_eq!(looking.len(), 4); + assert_eq!(looked.len(), 0); + } +} diff --git a/vm/src/chips/gadgets/global_accumulation.rs b/vm/src/chips/gadgets/global_accumulation.rs index 19cc9ad9..3cf39a60 100644 --- a/vm/src/chips/gadgets/global_accumulation.rs +++ b/vm/src/chips/gadgets/global_accumulation.rs @@ -236,3 +236,60 @@ impl GlobalAccumulationOperation { .assert_septic_ext_eq(final_digest.y, next_initial_digest.y); } } + +#[cfg(test)] +mod tests { + use super::*; + use crate::{machine::folder::SymbolicConstraintFolder, primitives::consts::PERMUTATION_WIDTH}; + use p3_koala_bear::KoalaBear; + use p3_uni_stark::{Entry, SymbolicVariable}; + use std::mem::size_of; + + #[test] + fn test_eval_accumulation_simple_eval() { + let var = SymbolicVariable::new(Entry::Main { offset: 0 }, 0); + + // create a interaction gadget + let interaction_gadget = GlobalInteractionOperation::> { + offset_bits: [var; 8], + x_coordinate: SepticBlock([var; 7]), + y_coordinate: SepticBlock([var; 7]), + y6_bit_decomp: [var; 30], + range_check_witness: var, + poseidon2_input: [var; PERMUTATION_WIDTH], + poseidon2_output: [var; PERMUTATION_WIDTH], + }; + + // create an accumulation gadget + let accumulation_gadget = GlobalAccumulationOperation::, 1> { + initial_digest: [SepticBlock([var; 7]); 2], + sum_checker: [SepticBlock([var; 7])], + cumulative_sum: [[SepticBlock([var; 7]); 2]], + }; + + // create a constraint builder + let mut builder = SymbolicConstraintFolder::new( + 0, + size_of::>(), + ); + + // evaluate with this gadget + GlobalAccumulationOperation::::eval_accumulation( + &mut builder, + [interaction_gadget], + [var], + [var], + accumulation_gadget, + accumulation_gadget, + ); + + // check the constraints and public values + assert_eq!(builder.constraints.len(), 65); + assert_eq!(builder.public_values.len(), 231); + + // check the looking (sending) and looked (receiving) lookups + let (looking, looked) = builder.lookups(); + assert_eq!(looking.len(), 0); + assert_eq!(looked.len(), 0); + } +} diff --git a/vm/src/chips/gadgets/global_interaction.rs b/vm/src/chips/gadgets/global_interaction.rs index 0404411b..184adbe5 100644 --- a/vm/src/chips/gadgets/global_interaction.rs +++ b/vm/src/chips/gadgets/global_interaction.rs @@ -225,3 +225,52 @@ impl GlobalInteractionOperation { ); } } + +#[cfg(test)] +mod tests { + use super::*; + use crate::machine::folder::SymbolicConstraintFolder; + use p3_koala_bear::KoalaBear; + use p3_uni_stark::{Entry, SymbolicVariable}; + + #[test] + fn test_global_interaction_gadget_simple_eval() { + let var = SymbolicVariable::new(Entry::Main { offset: 0 }, 0); + let values = [var; 7]; + + // create a new gadget + let gadget = GlobalInteractionOperation { + offset_bits: [var; 8], + x_coordinate: SepticBlock([var; 7]), + y_coordinate: SepticBlock([var; 7]), + y6_bit_decomp: [var; 30], + range_check_witness: var, + poseidon2_input: [var; 16], + poseidon2_output: [var; 16], + }; + + // create a constraint builder + let mut builder = + SymbolicConstraintFolder::new(0, size_of::>()); + + // evaluate with this gadget + GlobalInteractionOperation::::eval_single_digest( + &mut builder, + values.map(|v| v.into()), + gadget, + Default::default(), + Default::default(), + var, + var, + ); + + // check the constraints and public values + assert_eq!(builder.constraints.len(), 72); + assert_eq!(builder.public_values.len(), 231); + + // check the looking (sending) and looked (receiving) lookups + let (looking, looked) = builder.lookups(); + assert_eq!(looking.len(), 2); + assert_eq!(looked.len(), 0); + } +} diff --git a/vm/src/chips/gadgets/is_equal_word.rs b/vm/src/chips/gadgets/is_equal_word.rs index 699b3782..ee743458 100644 --- a/vm/src/chips/gadgets/is_equal_word.rs +++ b/vm/src/chips/gadgets/is_equal_word.rs @@ -52,3 +52,54 @@ impl IsEqualWordGadget { IsZeroWordGadget::::eval(builder, diff, cols.is_diff_zero, is_real.clone()); } } + +#[cfg(test)] +mod tests { + use super::*; + use crate::{chips::gadgets::is_zero::IsZeroGadget, machine::folder::SymbolicConstraintFolder}; + use p3_field::FieldAlgebra; + use p3_koala_bear::KoalaBear; + use p3_uni_stark::{Entry, SymbolicExpression, SymbolicVariable}; + use std::array; + + #[test] + fn test_is_equal_word_gadget_simple_eval() { + let expr = SymbolicExpression::Constant(KoalaBear::ZERO); + let var = SymbolicVariable::new(Entry::Main { offset: 0 }, 0); + let word = Word(array::from_fn(|_| expr.clone())); + + // create a new gadget + let is_zero_gadget = IsZeroWordGadget { + is_zero_byte: [IsZeroGadget { + inverse: var, + result: var, + }; 4], + is_lower_half_zero: var, + is_upper_half_zero: var, + result: var, + }; + let gadget = IsEqualWordGadget { + is_diff_zero: is_zero_gadget, + }; + // create a constraint builder + let mut builder = SymbolicConstraintFolder::new(0, size_of::>()); + + // evaluate with this gadget + IsEqualWordGadget::::eval( + &mut builder, + word.clone(), + word, + gadget, + Default::default(), + ); + + // check the constraints and public values + assert_eq!(builder.constraints.len(), 20); + assert_eq!(builder.public_values.len(), 231); + + // check the looking (sending) and looked (receiving) lookups + let (looking, looked) = builder.lookups(); + assert_eq!(looking.len(), 0); + assert_eq!(looked.len(), 0); + } +} diff --git a/vm/src/chips/gadgets/is_zero.rs b/vm/src/chips/gadgets/is_zero.rs index b4d4fb64..86fefe58 100644 --- a/vm/src/chips/gadgets/is_zero.rs +++ b/vm/src/chips/gadgets/is_zero.rs @@ -68,3 +68,37 @@ impl IsZeroGadget { .assert_zero(a.clone()); } } + +#[cfg(test)] +mod tests { + use super::*; + use crate::machine::folder::SymbolicConstraintFolder; + use p3_koala_bear::KoalaBear; + use p3_uni_stark::{Entry, SymbolicExpression, SymbolicVariable}; + + #[test] + fn test_is_zero_gadget_simple_eval() { + let expr = SymbolicExpression::Constant(KoalaBear::ZERO); + let var = SymbolicVariable::new(Entry::Main { offset: 0 }, 0); + + // create a new gadget + let gadget = IsZeroGadget { + inverse: var, + result: var, + }; + // create a constraint builder + let mut builder = SymbolicConstraintFolder::new(0, size_of::>()); + + // evaluate with this gadget + IsZeroGadget::::eval(&mut builder, expr, gadget, Default::default()); + + // check the constraints and public values + assert_eq!(builder.constraints.len(), 3); + assert_eq!(builder.public_values.len(), 231); + + // check the looking (sending) and looked (receiving) lookups + let (looking, looked) = builder.lookups(); + assert_eq!(looking.len(), 0); + assert_eq!(looked.len(), 0); + } +} diff --git a/vm/src/chips/gadgets/is_zero_word.rs b/vm/src/chips/gadgets/is_zero_word.rs index 8b8b82de..f5941495 100644 --- a/vm/src/chips/gadgets/is_zero_word.rs +++ b/vm/src/chips/gadgets/is_zero_word.rs @@ -85,3 +85,46 @@ impl IsZeroWordGadget { ); } } + +#[cfg(test)] +mod tests { + use super::*; + use crate::{chips::gadgets::is_zero::IsZeroGadget, machine::folder::SymbolicConstraintFolder}; + use p3_field::FieldAlgebra; + use p3_koala_bear::KoalaBear; + use p3_uni_stark::{Entry, SymbolicExpression, SymbolicVariable}; + use std::array; + + #[test] + fn test_is_zero_word_gadget_simple_eval() { + let expr = SymbolicExpression::Constant(KoalaBear::ZERO); + let var = SymbolicVariable::new(Entry::Main { offset: 0 }, 0); + let word = Word(array::from_fn(|_| expr.clone())); + + // create a new gadget + let is_zero_gadget = IsZeroGadget { + inverse: var, + result: var, + }; + let gadget = IsZeroWordGadget { + is_zero_byte: [is_zero_gadget; 4], + is_lower_half_zero: var, + is_upper_half_zero: var, + result: var, + }; + // create a constraint builder + let mut builder = SymbolicConstraintFolder::new(0, size_of::>()); + + // evaluate with this gadget + IsZeroWordGadget::::eval(&mut builder, word, gadget, Default::default()); + + // check the constraints and public values + assert_eq!(builder.constraints.len(), 19); + assert_eq!(builder.public_values.len(), 231); + + // check the looking (sending) and looked (receiving) lookups + let (looking, looked) = builder.lookups(); + assert_eq!(looking.len(), 0); + assert_eq!(looked.len(), 0); + } +} diff --git a/vm/src/chips/gadgets/not.rs b/vm/src/chips/gadgets/not.rs index b09beff4..1b0a5eb0 100644 --- a/vm/src/chips/gadgets/not.rs +++ b/vm/src/chips/gadgets/not.rs @@ -46,3 +46,35 @@ impl NotOperation { } } } + +#[cfg(test)] +mod tests { + use super::*; + use crate::machine::folder::SymbolicConstraintFolder; + use p3_field::FieldAlgebra; + use p3_koala_bear::KoalaBear; + use p3_uni_stark::{Entry, SymbolicVariable}; + + #[test] + fn test_not_gadget_simple_eval() { + let var = SymbolicVariable::new(Entry::Main { offset: 0 }, 0); + let word = Word([var; 4]); + + // create a new gadget + let gadget = NotOperation { value: word }; + // create a constraint builder + let mut builder = SymbolicConstraintFolder::new(0, size_of::>()); + + // evaluate with this gadget + NotOperation::::eval(&mut builder, word, gadget, KoalaBear::ZERO); + + // check the constraints and public values + assert_eq!(builder.constraints.len(), 4); + assert_eq!(builder.public_values.len(), 231); + + // check the looking (sending) and looked (receiving) lookups + let (looking, looked) = builder.lookups(); + assert_eq!(looking.len(), 2); + assert_eq!(looked.len(), 0); + } +} diff --git a/vm/src/chips/gadgets/xor.rs b/vm/src/chips/gadgets/xor.rs index b4a1271d..16d57d1d 100644 --- a/vm/src/chips/gadgets/xor.rs +++ b/vm/src/chips/gadgets/xor.rs @@ -55,3 +55,34 @@ impl XorOperation { } } } + +#[cfg(test)] +mod tests { + use super::*; + use crate::machine::folder::SymbolicConstraintFolder; + use p3_koala_bear::KoalaBear; + use p3_uni_stark::{Entry, SymbolicVariable}; + + #[test] + fn test_xor_gadget_simple_eval() { + let var = SymbolicVariable::new(Entry::Main { offset: 0 }, 0); + let word = Word([var; 4]); + + // create a new gadget + let gadget = XorOperation { value: word }; + // create a constraint builder + let mut builder = SymbolicConstraintFolder::new(0, size_of::>()); + + // evaluate with this gadget + XorOperation::::eval(&mut builder, word, word, gadget, var); + + // check the constraints and public values + assert_eq!(builder.constraints.len(), 0); + assert_eq!(builder.public_values.len(), 231); + + // check the looking (sending) and looked (receiving) lookups + let (looking, looked) = builder.lookups(); + assert_eq!(looking.len(), 4); + assert_eq!(looked.len(), 0); + } +} diff --git a/vm/src/emulator/riscv/emulator/instruction.rs b/vm/src/emulator/riscv/emulator/instruction.rs index 3838288b..c6c8a02d 100644 --- a/vm/src/emulator/riscv/emulator/instruction.rs +++ b/vm/src/emulator/riscv/emulator/instruction.rs @@ -3,6 +3,7 @@ use crate::{ chips::chips::riscv_memory::event::MemoryAccessPosition, compiler::riscv::{instruction::Instruction, opcode::Opcode, register::Register}, emulator::riscv::syscalls::{syscall_context::SyscallContext, SyscallCode}, + primitives::consts::MAX_PC, }; use tracing::debug; @@ -16,6 +17,7 @@ impl RiscvEmulator { let mut exit_code = 0u32; let mut clk = self.state.clk; let mut next_pc = self.state.pc.wrapping_add(4); + assert!(next_pc < MAX_PC); let rd: Register; let (a, b, c): (u32, u32, u32); diff --git a/vm/src/machine/folder.rs b/vm/src/machine/folder.rs index 0db402c9..78d3f702 100644 --- a/vm/src/machine/folder.rs +++ b/vm/src/machine/folder.rs @@ -29,12 +29,12 @@ use std::{ // SymbolicConstraintFolder for lookup-related variables and constraints // It also impls functions for SymbolicAirBuilder, thus replacing it pub struct SymbolicConstraintFolder { - preprocessed: RowMajorMatrix>, - main: RowMajorMatrix>, - looking: Vec>, - looked: Vec>, - constraints: Vec>, - public_values: Vec>, + pub(crate) preprocessed: RowMajorMatrix>, + pub(crate) main: RowMajorMatrix>, + pub(crate) looking: Vec>, + pub(crate) looked: Vec>, + pub(crate) constraints: Vec>, + pub(crate) public_values: Vec>, } impl SymbolicConstraintFolder { diff --git a/vm/src/primitives/consts.rs b/vm/src/primitives/consts.rs index 57bbed4e..c412add9 100644 --- a/vm/src/primitives/consts.rs +++ b/vm/src/primitives/consts.rs @@ -66,6 +66,7 @@ pub const BENCH_RECURSION_MAX_CHUNK_SIZE: u32 = 1 << 22; For RiscV */ pub const MAX_LOG_NUMBER_OF_CHUNKS: usize = 16; +pub const MAX_PC: u32 = 1 << 30; /* For recursion