diff --git a/evm/src/cpu/columns.rs b/evm/src/cpu/columns.rs index 66a87d9c..ab97cd4a 100644 --- a/evm/src/cpu/columns.rs +++ b/evm/src/cpu/columns.rs @@ -144,4 +144,8 @@ pub const KECCAK_INPUT_LIMBS: Range = START_KECCAK_INPUT..START_KECCAK_IN pub const START_KECCAK_OUTPUT: usize = KECCAK_INPUT_LIMBS.end; pub const KECCAK_OUTPUT_LIMBS: Range = START_KECCAK_OUTPUT..START_KECCAK_OUTPUT + 50; -pub const NUM_CPU_COLUMNS: usize = KECCAK_OUTPUT_LIMBS.end; +// Assuming a limb size of 16 bits. +pub const SIMPLE_LOGIC_INPUT0: Range = KECCAK_OUTPUT_LIMBS.end..KECCAK_OUTPUT_LIMBS.end + 16; +pub const SIMPLE_LOGIC_OUTPUT: Range = SIMPLE_LOGIC_INPUT0.end..SIMPLE_LOGIC_INPUT0.end + 16; + +pub const NUM_CPU_COLUMNS: usize = SIMPLE_LOGIC_OUTPUT.end; diff --git a/evm/src/cpu/cpu_stark.rs b/evm/src/cpu/cpu_stark.rs index a3ca826a..72897bd7 100644 --- a/evm/src/cpu/cpu_stark.rs +++ b/evm/src/cpu/cpu_stark.rs @@ -5,8 +5,7 @@ use plonky2::field::packed_field::PackedField; use plonky2::hash::hash_types::RichField; use crate::constraint_consumer::{ConstraintConsumer, RecursiveConstraintConsumer}; -use crate::cpu::columns; -use crate::cpu::decode; +use crate::cpu::{columns, decode, simple_logic}; use crate::permutation::PermutationPair; use crate::stark::Stark; use crate::vars::{StarkEvaluationTargets, StarkEvaluationVars}; @@ -19,6 +18,7 @@ pub struct CpuStark { impl CpuStark { pub fn generate(&self, local_values: &mut [F; columns::NUM_CPU_COLUMNS]) { decode::generate(local_values); + simple_logic::generate(local_values); } } @@ -35,6 +35,7 @@ impl, const D: usize> Stark for CpuStark, { decode::eval_packed_generic(vars.local_values, yield_constr); + simple_logic::eval_packed(vars.local_values, yield_constr); } fn eval_ext_circuit( @@ -44,6 +45,7 @@ impl, const D: usize> Stark for CpuStark, ) { decode::eval_ext_circuit(builder, vars.local_values, yield_constr); + simple_logic::eval_ext_circuit(builder, vars.local_values, yield_constr); } fn constraint_degree(&self) -> usize { diff --git a/evm/src/cpu/mod.rs b/evm/src/cpu/mod.rs index 5a2905bc..2db21ea9 100644 --- a/evm/src/cpu/mod.rs +++ b/evm/src/cpu/mod.rs @@ -1,3 +1,4 @@ pub(crate) mod columns; pub mod cpu_stark; pub(crate) mod decode; +mod simple_logic; diff --git a/evm/src/cpu/simple_logic/mod.rs b/evm/src/cpu/simple_logic/mod.rs new file mode 100644 index 00000000..bc4283f1 --- /dev/null +++ b/evm/src/cpu/simple_logic/mod.rs @@ -0,0 +1,34 @@ +mod not; + +use plonky2::field::extension_field::Extendable; +use plonky2::field::packed_field::PackedField; +use plonky2::hash::hash_types::RichField; +use plonky2::iop::ext_target::ExtensionTarget; + +use crate::constraint_consumer::{ConstraintConsumer, RecursiveConstraintConsumer}; +use crate::cpu::columns; + +pub fn generate(lv: &mut [F; columns::NUM_CPU_COLUMNS]) { + let cycle_filter = lv[columns::IS_CPU_CYCLE].to_canonical_u64(); + if cycle_filter == 0 { + return; + } + assert_eq!(cycle_filter, 1); + + not::generate(lv); +} + +pub fn eval_packed( + lv: &[P; columns::NUM_CPU_COLUMNS], + yield_constr: &mut ConstraintConsumer

, +) { + not::eval_packed(lv, yield_constr); +} + +pub fn eval_ext_circuit, const D: usize>( + builder: &mut plonky2::plonk::circuit_builder::CircuitBuilder, + lv: &[ExtensionTarget; columns::NUM_CPU_COLUMNS], + yield_constr: &mut RecursiveConstraintConsumer, +) { + not::eval_ext_circuit(builder, lv, yield_constr); +} diff --git a/evm/src/cpu/simple_logic/not.rs b/evm/src/cpu/simple_logic/not.rs new file mode 100644 index 00000000..e0905c41 --- /dev/null +++ b/evm/src/cpu/simple_logic/not.rs @@ -0,0 +1,65 @@ +use plonky2::field::extension_field::Extendable; +use plonky2::field::field_types::Field; +use plonky2::field::packed_field::PackedField; +use plonky2::hash::hash_types::RichField; +use plonky2::iop::ext_target::ExtensionTarget; + +use crate::constraint_consumer::{ConstraintConsumer, RecursiveConstraintConsumer}; +use crate::cpu::columns; + +const LIMB_SIZE: usize = 16; +const ALL_1_LIMB: u64 = (1 << LIMB_SIZE) - 1; + +pub fn generate(lv: &mut [F; columns::NUM_CPU_COLUMNS]) { + let is_not_filter = lv[columns::IS_NOT].to_canonical_u64(); + if is_not_filter == 0 { + return; + } + assert_eq!(is_not_filter, 1); + + for (input_col, output_col) in columns::SIMPLE_LOGIC_INPUT0.zip(columns::SIMPLE_LOGIC_OUTPUT) { + let input = lv[input_col].to_canonical_u64(); + assert_eq!(input >> LIMB_SIZE, 0); + let output = input ^ ALL_1_LIMB; + lv[output_col] = F::from_canonical_u64(output); + } +} + +pub fn eval_packed( + lv: &[P; columns::NUM_CPU_COLUMNS], + yield_constr: &mut ConstraintConsumer

, +) { + // This is simple: just do output = 0xffff - input. + let cycle_filter = lv[columns::IS_CPU_CYCLE]; + let is_not_filter = lv[columns::IS_NOT]; + let filter = cycle_filter * is_not_filter; + for (input_col, output_col) in columns::SIMPLE_LOGIC_INPUT0.zip(columns::SIMPLE_LOGIC_OUTPUT) { + let input = lv[input_col]; + let output = lv[output_col]; + yield_constr + .constraint(filter * (output + input - P::Scalar::from_canonical_u64(ALL_1_LIMB))); + } +} + +pub fn eval_ext_circuit, const D: usize>( + builder: &mut plonky2::plonk::circuit_builder::CircuitBuilder, + lv: &[ExtensionTarget; columns::NUM_CPU_COLUMNS], + yield_constr: &mut RecursiveConstraintConsumer, +) { + let cycle_filter = lv[columns::IS_CPU_CYCLE]; + let is_not_filter = lv[columns::IS_NOT]; + let filter = builder.mul_extension(cycle_filter, is_not_filter); + for (input_col, output_col) in columns::SIMPLE_LOGIC_INPUT0.zip(columns::SIMPLE_LOGIC_OUTPUT) { + let input = lv[input_col]; + let output = lv[output_col]; + let constr = builder.add_extension(output, input); + let constr = builder.arithmetic_extension( + F::ONE, + -F::from_canonical_u64(ALL_1_LIMB), + filter, + constr, + filter, + ); + yield_constr.constraint(builder, constr); + } +}