mirror of
https://github.com/logos-storage/plonky2.git
synced 2026-01-03 14:23:07 +00:00
Combine EQ and ISZERO flags
This commit is contained in:
parent
dc7e0aa79b
commit
7829dccf83
@ -22,9 +22,8 @@ pub struct OpsColumnsView<T: Copy> {
|
||||
pub submod: T,
|
||||
pub lt: T,
|
||||
pub gt: T,
|
||||
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 logic_op: T, // Combines AND, OR and XOR flags.
|
||||
pub eq_iszero: T, // Combines EQ and ISZERO flags.
|
||||
pub logic_op: T, // Combines AND, OR and XOR flags.
|
||||
pub not: T,
|
||||
pub byte: T,
|
||||
// TODO: combine SHL and SHR into one flag
|
||||
|
||||
@ -8,7 +8,7 @@ use crate::constraint_consumer::{ConstraintConsumer, RecursiveConstraintConsumer
|
||||
use crate::cpu::columns::{CpuColumnsView, COL_MAP};
|
||||
use crate::cpu::kernel::aggregator::KERNEL;
|
||||
|
||||
const NATIVE_INSTRUCTIONS: [usize; 30] = [
|
||||
const NATIVE_INSTRUCTIONS: [usize; 29] = [
|
||||
COL_MAP.op.add,
|
||||
COL_MAP.op.mul,
|
||||
COL_MAP.op.sub,
|
||||
@ -21,8 +21,7 @@ const NATIVE_INSTRUCTIONS: [usize; 30] = [
|
||||
COL_MAP.op.subfp254,
|
||||
COL_MAP.op.lt,
|
||||
COL_MAP.op.gt,
|
||||
COL_MAP.op.eq,
|
||||
COL_MAP.op.iszero,
|
||||
COL_MAP.op.eq_iszero,
|
||||
COL_MAP.op.logic_op,
|
||||
COL_MAP.op.not,
|
||||
COL_MAP.op.shl,
|
||||
|
||||
@ -22,7 +22,7 @@ use crate::cpu::columns::{CpuColumnsView, COL_MAP};
|
||||
/// behavior.
|
||||
/// 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.
|
||||
const OPCODES: [(u8, usize, bool, usize); 34] = [
|
||||
const OPCODES: [(u8, usize, bool, usize); 33] = [
|
||||
// (start index of block, number of top bits to check (log2), kernel-only, flag column)
|
||||
(0x01, 0, false, COL_MAP.op.add),
|
||||
(0x02, 0, false, COL_MAP.op.mul),
|
||||
@ -36,8 +36,7 @@ const OPCODES: [(u8, usize, bool, usize); 34] = [
|
||||
(0x0e, 0, true, COL_MAP.op.subfp254),
|
||||
(0x10, 0, false, COL_MAP.op.lt),
|
||||
(0x11, 0, false, COL_MAP.op.gt),
|
||||
(0x14, 0, false, COL_MAP.op.eq),
|
||||
(0x15, 0, false, COL_MAP.op.iszero),
|
||||
(0x14, 1, false, COL_MAP.op.eq_iszero),
|
||||
// AND, OR and XOR flags are handled partly manually here, and partly through the Logic table CTL.
|
||||
(0x19, 0, false, COL_MAP.op.not),
|
||||
(0x1a, 0, false, COL_MAP.op.byte),
|
||||
@ -64,9 +63,8 @@ const OPCODES: [(u8, usize, bool, usize); 34] = [
|
||||
pub fn generate<F: RichField>(lv: &mut CpuColumnsView<F>) {
|
||||
let cycle_filter = lv.is_cpu_cycle;
|
||||
if cycle_filter == F::ZERO {
|
||||
// These columns cannot be shared.
|
||||
lv.op.eq = F::ZERO;
|
||||
lv.op.iszero = F::ZERO;
|
||||
// This column cannot be shared.
|
||||
lv.op.eq_iszero = F::ZERO;
|
||||
return;
|
||||
}
|
||||
// This assert is not _strictly_ necessary, but I include it as a sanity check.
|
||||
|
||||
@ -31,8 +31,7 @@ const SIMPLE_OPCODES: OpsColumnsView<Option<u32>> = OpsColumnsView {
|
||||
submod: KERNEL_ONLY_INSTR,
|
||||
lt: G_VERYLOW,
|
||||
gt: G_VERYLOW,
|
||||
eq: G_VERYLOW,
|
||||
iszero: G_VERYLOW,
|
||||
eq_iszero: G_VERYLOW,
|
||||
logic_op: G_VERYLOW,
|
||||
not: G_VERYLOW,
|
||||
byte: G_VERYLOW,
|
||||
|
||||
@ -8,6 +8,7 @@ use plonky2::iop::ext_target::ExtensionTarget;
|
||||
|
||||
use crate::constraint_consumer::{ConstraintConsumer, RecursiveConstraintConsumer};
|
||||
use crate::cpu::columns::CpuColumnsView;
|
||||
use crate::cpu::stack::{self, EQ_STACK_BEHAVIOR, IS_ZERO_STACK_BEHAVIOR};
|
||||
|
||||
fn limbs(x: U256) -> [u32; 8] {
|
||||
let mut res = [0; 8];
|
||||
@ -57,9 +58,10 @@ pub fn eval_packed<P: PackedField>(
|
||||
let input1 = lv.mem_channels[1].value;
|
||||
let output = lv.mem_channels[2].value;
|
||||
|
||||
let eq_filter = lv.op.eq;
|
||||
let iszero_filter = lv.op.iszero;
|
||||
let eq_or_iszero_filter = eq_filter + iszero_filter;
|
||||
// EQ (0x14) and ISZERO (0x15) are differentiated by their first opcode bit.
|
||||
let eq_filter = lv.op.eq_iszero * (P::ONES - lv.opcode_bits[0]);
|
||||
let iszero_filter = lv.op.eq_iszero * lv.opcode_bits[0];
|
||||
let eq_or_iszero_filter = lv.op.eq_iszero;
|
||||
|
||||
let equal = output[0];
|
||||
let unequal = P::ONES - equal;
|
||||
@ -90,6 +92,15 @@ pub fn eval_packed<P: PackedField>(
|
||||
.map(|(limb0, limb1, diff_pinv_el)| (limb0 - limb1) * diff_pinv_el)
|
||||
.sum();
|
||||
yield_constr.constraint(eq_or_iszero_filter * (dot - unequal));
|
||||
|
||||
// Stack constraints.
|
||||
stack::eval_packed_one(lv, eq_filter, EQ_STACK_BEHAVIOR.unwrap(), yield_constr);
|
||||
stack::eval_packed_one(
|
||||
lv,
|
||||
iszero_filter,
|
||||
IS_ZERO_STACK_BEHAVIOR.unwrap(),
|
||||
yield_constr,
|
||||
);
|
||||
}
|
||||
|
||||
pub fn eval_ext_circuit<F: RichField + Extendable<D>, const D: usize>(
|
||||
@ -105,9 +116,12 @@ pub fn eval_ext_circuit<F: RichField + Extendable<D>, const D: usize>(
|
||||
let input1 = lv.mem_channels[1].value;
|
||||
let output = lv.mem_channels[2].value;
|
||||
|
||||
let eq_filter = lv.op.eq;
|
||||
let iszero_filter = lv.op.iszero;
|
||||
let eq_or_iszero_filter = builder.add_extension(eq_filter, iszero_filter);
|
||||
// EQ (0x14) and ISZERO (0x15) are differentiated by their first opcode bit.
|
||||
let eq_filter = builder.mul_extension(lv.op.eq_iszero, lv.opcode_bits[0]);
|
||||
let eq_filter = builder.sub_extension(lv.op.eq_iszero, eq_filter);
|
||||
|
||||
let iszero_filter = builder.mul_extension(lv.op.eq_iszero, lv.opcode_bits[0]);
|
||||
let eq_or_iszero_filter = lv.op.eq_iszero;
|
||||
|
||||
let equal = output[0];
|
||||
let unequal = builder.sub_extension(one, equal);
|
||||
@ -154,4 +168,20 @@ pub fn eval_ext_circuit<F: RichField + Extendable<D>, const D: usize>(
|
||||
let constr = builder.mul_extension(eq_or_iszero_filter, constr);
|
||||
yield_constr.constraint(builder, constr);
|
||||
}
|
||||
|
||||
// Stack constraints.
|
||||
stack::eval_ext_circuit_one(
|
||||
builder,
|
||||
lv,
|
||||
eq_filter,
|
||||
EQ_STACK_BEHAVIOR.unwrap(),
|
||||
yield_constr,
|
||||
);
|
||||
stack::eval_ext_circuit_one(
|
||||
builder,
|
||||
lv,
|
||||
iszero_filter,
|
||||
IS_ZERO_STACK_BEHAVIOR.unwrap(),
|
||||
yield_constr,
|
||||
);
|
||||
}
|
||||
|
||||
@ -12,7 +12,7 @@ use crate::cpu::membus::NUM_GP_CHANNELS;
|
||||
use crate::memory::segments::Segment;
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
struct StackBehavior {
|
||||
pub(crate) struct StackBehavior {
|
||||
num_pops: usize,
|
||||
pushes: bool,
|
||||
disable_other_channels: bool,
|
||||
@ -53,8 +53,7 @@ const STACK_BEHAVIORS: OpsColumnsView<Option<StackBehavior>> = OpsColumnsView {
|
||||
submod: BASIC_TERNARY_OP,
|
||||
lt: BASIC_BINARY_OP,
|
||||
gt: BASIC_BINARY_OP,
|
||||
eq: BASIC_BINARY_OP,
|
||||
iszero: BASIC_UNARY_OP,
|
||||
eq_iszero: None, // EQ is binary, IS_ZERO is unary.
|
||||
logic_op: BASIC_BINARY_OP,
|
||||
not: BASIC_UNARY_OP,
|
||||
byte: BASIC_BINARY_OP,
|
||||
@ -140,7 +139,10 @@ const STACK_BEHAVIORS: OpsColumnsView<Option<StackBehavior>> = OpsColumnsView {
|
||||
}),
|
||||
};
|
||||
|
||||
fn eval_packed_one<P: PackedField>(
|
||||
pub(crate) const EQ_STACK_BEHAVIOR: Option<StackBehavior> = BASIC_BINARY_OP;
|
||||
pub(crate) const IS_ZERO_STACK_BEHAVIOR: Option<StackBehavior> = BASIC_UNARY_OP;
|
||||
|
||||
pub(crate) fn eval_packed_one<P: PackedField>(
|
||||
lv: &CpuColumnsView<P>,
|
||||
filter: P,
|
||||
stack_behavior: StackBehavior,
|
||||
@ -201,7 +203,7 @@ pub fn eval_packed<P: PackedField>(
|
||||
}
|
||||
}
|
||||
|
||||
fn eval_ext_circuit_one<F: RichField + Extendable<D>, const D: usize>(
|
||||
pub(crate) fn eval_ext_circuit_one<F: RichField + Extendable<D>, const D: usize>(
|
||||
builder: &mut plonky2::plonk::circuit_builder::CircuitBuilder<F, D>,
|
||||
lv: &CpuColumnsView<ExtensionTarget<D>>,
|
||||
filter: ExtensionTarget<D>,
|
||||
|
||||
@ -156,10 +156,9 @@ fn fill_op_flag<F: Field>(op: Operation, row: &mut CpuColumnsView<F>) {
|
||||
Operation::Push(1..) => &mut flags.push,
|
||||
Operation::Dup(_) => &mut flags.dup,
|
||||
Operation::Swap(_) => &mut flags.swap,
|
||||
Operation::Iszero => &mut flags.iszero,
|
||||
Operation::Iszero | Operation::Eq => &mut flags.eq_iszero,
|
||||
Operation::Not => &mut flags.not,
|
||||
Operation::Syscall(_, _, _) => &mut flags.syscall,
|
||||
Operation::Eq => &mut flags.eq,
|
||||
Operation::BinaryLogic(_) => &mut flags.logic_op,
|
||||
Operation::BinaryArithmetic(arithmetic::BinaryOperator::Add) => &mut flags.add,
|
||||
Operation::BinaryArithmetic(arithmetic::BinaryOperator::Mul) => &mut flags.mul,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user