use miden_core::field::PrimeCharacteristicRing;
use miden_crypto::stark::air::AirBuilder;
use crate::{MainCols, MidenAirBuilder, constraints::utils::BoolNot};
#[derive(Clone)]
pub struct ChipletFlags<E> {
pub is_active: E,
pub is_transition: E,
pub is_last: E,
pub next_is_first: E,
}
#[derive(Clone)]
pub struct ChipletSelectors<E> {
pub controller: ChipletFlags<E>,
pub permutation: ChipletFlags<E>,
pub bitwise: ChipletFlags<E>,
pub memory: ChipletFlags<E>,
pub ace: ChipletFlags<E>,
}
pub fn build_chiplet_selectors<AB>(
builder: &mut AB,
local: &MainCols<AB::Var>,
next: &MainCols<AB::Var>,
) -> ChipletSelectors<AB::Expr>
where
AB: MidenAirBuilder,
{
let sel = local.chiplet_selectors();
let sel_next = next.chiplet_selectors();
let s_ctrl: AB::Expr = sel[0].into();
let s_ctrl_next: AB::Expr = sel_next[0].into();
let s_perm: AB::Expr = sel[1].into();
let s_perm_next: AB::Expr = sel_next[1].into();
let s_ctrl_or_s_perm = s_ctrl.clone() + s_perm.clone();
let s_ctrl_or_s_perm_next = s_ctrl_next.clone() + s_perm_next.clone();
let s1: AB::Expr = sel[2].into();
let s2: AB::Expr = sel[3].into();
let s3: AB::Expr = sel[4].into();
let s4: AB::Expr = sel[5].into();
let s1_next: AB::Expr = sel_next[2].into();
let s2_next: AB::Expr = sel_next[3].into();
let s3_next: AB::Expr = sel_next[4].into();
let s4_next: AB::Expr = sel_next[5].into();
let s0: AB::Expr = s_ctrl_or_s_perm.not();
builder.assert_bool(s_ctrl.clone());
builder.assert_bool(s_perm.clone());
builder.assert_bool(s_ctrl_or_s_perm);
{
let builder = &mut builder.when_transition();
builder.when(s_ctrl.clone()).assert_one(s_ctrl_or_s_perm_next);
builder.when(s_perm.clone()).assert_zero(s_ctrl_next.clone());
{
let builder = &mut builder.when(s0.clone());
builder.assert_zero(s_ctrl_next.clone());
builder.assert_zero(s_perm_next.clone());
}
}
let s01 = s0.clone() * s1.clone();
let s012 = s01.clone() * s2.clone();
let s0123 = s012.clone() * s3.clone();
builder.when(s0.clone()).assert_bool(s1.clone());
builder.when(s01.clone()).assert_bool(s2.clone());
builder.when(s012.clone()).assert_bool(s3.clone());
builder.when(s0123.clone()).assert_bool(s4.clone());
let s01234 = s0123.clone() * s4.clone();
{
let builder = &mut builder.when_transition();
builder.when(s01.clone()).assert_eq(s1_next.clone(), s1.clone());
builder.when(s012.clone()).assert_eq(s2_next.clone(), s2.clone());
builder.when(s0123.clone()).assert_eq(s3_next.clone(), s3.clone());
builder.when(s01234).assert_eq(s4_next, s4.clone());
}
{
let builder = &mut builder.when_last_row();
builder.assert_zero(s_ctrl.clone());
builder.assert_zero(s_perm.clone());
builder.assert_one(s1);
builder.assert_one(s2);
builder.assert_one(s3);
builder.assert_one(s4);
}
let not_s1_next = s1_next.not();
let not_s2_next = s2_next.not();
let not_s3_next = s3_next.not();
let is_transition_flag: AB::Expr = builder.is_transition();
let ctrl_is_active = s_ctrl.clone();
let ctrl_is_transition = is_transition_flag.clone() * s_ctrl.clone() * s_ctrl_next.clone();
let ctrl_is_last = s_ctrl * s_ctrl_next.not();
let ctrl_next_is_first = AB::Expr::ZERO;
let perm_is_active = s_perm.clone();
let perm_is_transition = is_transition_flag.clone() * s_perm.clone() * s_perm_next.clone();
let perm_is_last = s_perm * s_perm_next.not();
let perm_next_is_first = ctrl_is_last.clone() * s_perm_next;
let is_bitwise = s0.clone() - s01.clone();
let is_memory = s01.clone() - s012.clone();
let is_ace = s012.clone() - s0123;
let is_bitwise_last = is_bitwise.clone() * s1_next;
let is_memory_last = is_memory.clone() * s2_next;
let is_ace_last = is_ace.clone() * s3_next;
let next_is_bitwise_first = perm_is_last.clone() * not_s1_next.clone();
let next_is_memory_first = is_bitwise_last.clone() * not_s2_next.clone();
let next_is_ace_first = is_memory_last.clone() * not_s3_next.clone();
let bitwise_transition = is_transition_flag.clone() * s0 * not_s1_next;
let memory_transition = is_transition_flag.clone() * s01 * not_s2_next;
let ace_transition = is_transition_flag * s012 * not_s3_next;
ChipletSelectors {
controller: ChipletFlags {
is_active: ctrl_is_active,
is_transition: ctrl_is_transition,
is_last: ctrl_is_last,
next_is_first: ctrl_next_is_first,
},
permutation: ChipletFlags {
is_active: perm_is_active,
is_transition: perm_is_transition,
is_last: perm_is_last,
next_is_first: perm_next_is_first,
},
bitwise: ChipletFlags {
is_active: is_bitwise,
is_transition: bitwise_transition,
is_last: is_bitwise_last,
next_is_first: next_is_bitwise_first,
},
memory: ChipletFlags {
is_active: is_memory,
is_transition: memory_transition,
is_last: is_memory_last,
next_is_first: next_is_memory_first,
},
ace: ChipletFlags {
is_active: is_ace,
is_transition: ace_transition,
is_last: is_ace_last,
next_is_first: next_is_ace_first,
},
}
}