Combine all logic flags together

This commit is contained in:
Robin Salen 2023-08-11 10:17:45 -04:00
parent 437f57a862
commit e10eaad09b
No known key found for this signature in database
GPG Key ID: FB87BACFB3CB2007
8 changed files with 38 additions and 22 deletions

View File

@ -24,9 +24,7 @@ pub struct OpsColumnsView<T: Copy> {
pub gt: T, pub gt: T,
pub eq: T, // Note: This column must be 0 when is_cpu_cycle = 0. pub eq: T, // Note: This column must be 0 when is_cpu_cycle = 0.
pub iszero: T, // Note: This column must be 0 when is_cpu_cycle = 0. pub iszero: T, // Note: This column must be 0 when is_cpu_cycle = 0.
// TODO: combine AND/OR, and XOR into one flag pub logic_op: T, // Combines AND, OR and XOR flags.
pub and_or: T,
pub xor: T,
pub not: T, pub not: T,
pub byte: T, pub byte: T,
// TODO: combine SHL and SHR into one flag // TODO: combine SHL and SHR into one flag

View File

@ -8,7 +8,7 @@ use crate::constraint_consumer::{ConstraintConsumer, RecursiveConstraintConsumer
use crate::cpu::columns::{CpuColumnsView, COL_MAP}; use crate::cpu::columns::{CpuColumnsView, COL_MAP};
use crate::cpu::kernel::aggregator::KERNEL; use crate::cpu::kernel::aggregator::KERNEL;
const NATIVE_INSTRUCTIONS: [usize; 31] = [ const NATIVE_INSTRUCTIONS: [usize; 30] = [
COL_MAP.op.add, COL_MAP.op.add,
COL_MAP.op.mul, COL_MAP.op.mul,
COL_MAP.op.sub, COL_MAP.op.sub,
@ -23,8 +23,7 @@ const NATIVE_INSTRUCTIONS: [usize; 31] = [
COL_MAP.op.gt, COL_MAP.op.gt,
COL_MAP.op.eq, COL_MAP.op.eq,
COL_MAP.op.iszero, COL_MAP.op.iszero,
COL_MAP.op.and_or, COL_MAP.op.logic_op,
COL_MAP.op.xor,
COL_MAP.op.not, COL_MAP.op.not,
COL_MAP.op.shl, COL_MAP.op.shl,
COL_MAP.op.shr, COL_MAP.op.shr,

View File

@ -89,7 +89,7 @@ pub fn ctl_data_logic<F: Field>() -> Vec<Column<F>> {
} }
pub fn ctl_filter_logic<F: Field>() -> Column<F> { pub fn ctl_filter_logic<F: Field>() -> Column<F> {
Column::sum([COL_MAP.op.and_or, COL_MAP.op.xor]) Column::single(COL_MAP.op.logic_op)
} }
pub fn ctl_arithmetic_base_rows<F: Field>() -> TableWithColumns<F> { pub fn ctl_arithmetic_base_rows<F: Field>() -> TableWithColumns<F> {

View File

@ -22,7 +22,7 @@ use crate::cpu::columns::{CpuColumnsView, COL_MAP};
/// behavior. /// behavior.
/// Note: invalid opcodes are not represented here. _Any_ opcode is permitted to decode to /// Note: invalid opcodes are not represented here. _Any_ opcode is permitted to decode to
/// `is_invalid`. The kernel then verifies that the opcode was _actually_ invalid. /// `is_invalid`. The kernel then verifies that the opcode was _actually_ invalid.
const OPCODES: [(u8, usize, bool, usize); 36] = [ const OPCODES: [(u8, usize, bool, usize); 34] = [
// (start index of block, number of top bits to check (log2), kernel-only, flag column) // (start index of block, number of top bits to check (log2), kernel-only, flag column)
(0x01, 0, false, COL_MAP.op.add), (0x01, 0, false, COL_MAP.op.add),
(0x02, 0, false, COL_MAP.op.mul), (0x02, 0, false, COL_MAP.op.mul),
@ -38,8 +38,7 @@ const OPCODES: [(u8, usize, bool, usize); 36] = [
(0x11, 0, false, COL_MAP.op.gt), (0x11, 0, false, COL_MAP.op.gt),
(0x14, 0, false, COL_MAP.op.eq), (0x14, 0, false, COL_MAP.op.eq),
(0x15, 0, false, COL_MAP.op.iszero), (0x15, 0, false, COL_MAP.op.iszero),
(0x16, 1, false, COL_MAP.op.and_or), // AND, OR and XOR flags are handled directly on the logic table side
(0x18, 0, false, COL_MAP.op.xor),
(0x19, 0, false, COL_MAP.op.not), (0x19, 0, false, COL_MAP.op.not),
(0x1a, 0, false, COL_MAP.op.byte), (0x1a, 0, false, COL_MAP.op.byte),
(0x1b, 0, false, COL_MAP.op.shl), (0x1b, 0, false, COL_MAP.op.shl),
@ -143,11 +142,21 @@ pub fn eval_packed_generic<P: PackedField>(
let flag = lv[flag_col]; let flag = lv[flag_col];
yield_constr.constraint(cycle_filter * flag * (flag - P::ONES)); yield_constr.constraint(cycle_filter * flag * (flag - P::ONES));
} }
// Manually check for the logic_op flag combining AND, OR and XOR.
// TODO: This would go away once cycle_filter is replaced by the sum
// of all CPU opcode flags.
let flag = lv.op.logic_op;
yield_constr.constraint(cycle_filter * flag * (flag - P::ONES));
// Now check that they sum to 0 or 1. // Now check that they sum to 0 or 1.
// Include the logic_op flag encompassing AND, OR and XOR opcodes.
// TODO: This would go away once cycle_filter is replaced by the sum
// of all CPU opcode flags.
let flag_sum: P = OPCODES let flag_sum: P = OPCODES
.into_iter() .into_iter()
.map(|(_, _, _, flag_col)| lv[flag_col]) .map(|(_, _, _, flag_col)| lv[flag_col])
.sum::<P>(); .sum::<P>()
+ lv.op.logic_op;
yield_constr.constraint(cycle_filter * flag_sum * (flag_sum - P::ONES)); yield_constr.constraint(cycle_filter * flag_sum * (flag_sum - P::ONES));
// Finally, classify all opcodes, together with the kernel flag, into blocks // Finally, classify all opcodes, together with the kernel flag, into blocks
@ -211,9 +220,20 @@ pub fn eval_ext_circuit<F: RichField + Extendable<D>, const D: usize>(
let constr = builder.mul_extension(cycle_filter, constr); let constr = builder.mul_extension(cycle_filter, constr);
yield_constr.constraint(builder, constr); yield_constr.constraint(builder, constr);
} }
// Manually check for the logic_op flag combining AND, OR and XOR.
// TODO: This would go away once cycle_filter is replaced by the sum
// of all CPU opcode flags.
let flag = lv.op.logic_op;
let constr = builder.mul_sub_extension(flag, flag, flag);
let constr = builder.mul_extension(cycle_filter, constr);
yield_constr.constraint(builder, constr);
// Now check that they sum to 0 or 1. // Now check that they sum to 0 or 1.
// Include the logic_op flag encompassing AND, OR and XOR opcodes.
// TODO: This would go away once cycle_filter is replaced by the sum
// of all CPU opcode flags.
{ {
let mut flag_sum = builder.zero_extension(); let mut flag_sum = lv.op.logic_op;
for (_, _, _, flag_col) in OPCODES { for (_, _, _, flag_col) in OPCODES {
let flag = lv[flag_col]; let flag = lv[flag_col];
flag_sum = builder.add_extension(flag_sum, flag); flag_sum = builder.add_extension(flag_sum, flag);

View File

@ -33,8 +33,7 @@ const SIMPLE_OPCODES: OpsColumnsView<Option<u32>> = OpsColumnsView {
gt: G_VERYLOW, gt: G_VERYLOW,
eq: G_VERYLOW, eq: G_VERYLOW,
iszero: G_VERYLOW, iszero: G_VERYLOW,
and_or: G_VERYLOW, logic_op: G_VERYLOW,
xor: G_VERYLOW,
not: G_VERYLOW, not: G_VERYLOW,
byte: G_VERYLOW, byte: G_VERYLOW,
shl: G_VERYLOW, shl: G_VERYLOW,

View File

@ -55,8 +55,7 @@ const STACK_BEHAVIORS: OpsColumnsView<Option<StackBehavior>> = OpsColumnsView {
gt: BASIC_BINARY_OP, gt: BASIC_BINARY_OP,
eq: BASIC_BINARY_OP, eq: BASIC_BINARY_OP,
iszero: BASIC_UNARY_OP, iszero: BASIC_UNARY_OP,
and_or: BASIC_BINARY_OP, logic_op: BASIC_BINARY_OP,
xor: BASIC_BINARY_OP,
not: BASIC_UNARY_OP, not: BASIC_UNARY_OP,
byte: BASIC_BINARY_OP, byte: BASIC_BINARY_OP,
shl: Some(StackBehavior { shl: Some(StackBehavior {

View File

@ -52,6 +52,10 @@ pub(crate) mod columns {
} }
pub fn ctl_data<F: Field>() -> Vec<Column<F>> { pub fn ctl_data<F: Field>() -> Vec<Column<F>> {
// We scale each filter flag with the associated opcode value.
// If a logic operation is happening on the CPU side, the CTL
// will enforce that the reconstructed opcode value from the
// opcode bits matches.
let mut res = vec![Column::linear_combination([ let mut res = vec![Column::linear_combination([
(columns::IS_AND, F::from_canonical_u8(0x16)), (columns::IS_AND, F::from_canonical_u8(0x16)),
(columns::IS_OR, F::from_canonical_u8(0x17)), (columns::IS_OR, F::from_canonical_u8(0x17)),

View File

@ -160,10 +160,7 @@ fn fill_op_flag<F: Field>(op: Operation, row: &mut CpuColumnsView<F>) {
Operation::Not => &mut flags.not, Operation::Not => &mut flags.not,
Operation::Syscall(_, _, _) => &mut flags.syscall, Operation::Syscall(_, _, _) => &mut flags.syscall,
Operation::Eq => &mut flags.eq, Operation::Eq => &mut flags.eq,
Operation::BinaryLogic(logic::Op::And) | Operation::BinaryLogic(logic::Op::Or) => { Operation::BinaryLogic(_) => &mut flags.logic_op,
&mut flags.and_or
}
Operation::BinaryLogic(logic::Op::Xor) => &mut flags.xor,
Operation::BinaryArithmetic(arithmetic::BinaryOperator::Add) => &mut flags.add, Operation::BinaryArithmetic(arithmetic::BinaryOperator::Add) => &mut flags.add,
Operation::BinaryArithmetic(arithmetic::BinaryOperator::Mul) => &mut flags.mul, Operation::BinaryArithmetic(arithmetic::BinaryOperator::Mul) => &mut flags.mul,
Operation::BinaryArithmetic(arithmetic::BinaryOperator::Sub) => &mut flags.sub, Operation::BinaryArithmetic(arithmetic::BinaryOperator::Sub) => &mut flags.sub,