use core::{array, borrow::Borrow};
use miden_core::field::PrimeCharacteristicRing;
use crate::{
constraints::{
chiplets::columns::PeriodicCols,
lookup::{
chiplet_air::{ChipletBusContext, ChipletLookupBuilder},
messages::{AceWireMsg, HasherPermLinkMsg},
},
utils::BoolNot,
},
lookup::{Deg, LookupBatch, LookupColumn, LookupGroup},
};
pub(in crate::constraints::lookup) const MAX_INTERACTIONS_PER_ROW: usize = 3;
pub(in crate::constraints::lookup) fn emit_v_wiring<LB>(
builder: &mut LB,
ctx: &ChipletBusContext<LB>,
) where
LB: ChipletLookupBuilder,
{
let local = ctx.local;
let ace_flag = ctx.chiplet_active.ace.clone();
let ace = local.ace();
let ace_read = ace.read();
let ace_eval = ace.eval();
let ace_clk = ace.clk;
let ace_ctx = ace.ctx;
let id_0 = ace.id_0;
let id_1 = ace.id_1;
let id_2 = ace_eval.id_2;
let v_0 = ace.v_0;
let v_1 = ace.v_1;
let v_2 = ace_eval.v_2;
let m_0 = ace_read.m_0;
let m_1 = ace_read.m_1;
let sblock: LB::Expr = ace.s_block.into();
let (perm_row0_select, perm_row15_select): (LB::Expr, LB::Expr) = {
let periodic: &PeriodicCols<LB::PeriodicVar> = builder.periodic_values().borrow();
let h = periodic.hasher;
let is_init_ext: LB::Expr = h.is_init_ext.into();
let is_ext: LB::Expr = h.is_ext.into();
let is_packed_int: LB::Expr = h.is_packed_int.into();
let is_int_ext: LB::Expr = h.is_int_ext.into();
let not_cycle_end = is_init_ext.clone() + is_ext + is_packed_int + is_int_ext;
(is_init_ext, LB::Expr::ONE - not_cycle_end)
};
let ctrl = local.controller();
let s0c: LB::Expr = ctrl.s0.into();
let s1c: LB::Expr = ctrl.s1.into();
let is_input = s0c.clone();
let is_output = (LB::Expr::ONE - s0c) * (LB::Expr::ONE - s1c);
let controller_flag = ctx.chiplet_active.controller.clone();
let permutation_flag = ctx.chiplet_active.permutation.clone();
let f_ctrl_input = controller_flag.clone() * is_input;
let f_ctrl_output = controller_flag * is_output;
let f_perm_row0 = permutation_flag.clone() * perm_row0_select;
let f_perm_row15 = permutation_flag * perm_row15_select;
let ctrl_state: [LB::Var; 12] = array::from_fn(|i| ctrl.state[i]);
let perm = local.permutation();
let perm_state: [LB::Var; 12] = array::from_fn(|i| perm.state[i]);
let perm_mult = perm.multiplicity;
builder.next_column(
|col| {
col.group(
"ace_perm_link",
|g| {
g.batch(
"ace_wiring",
ace_flag,
move |b| {
let m_0: LB::Expr = m_0.into();
let m_1: LB::Expr = m_1.into();
let wire_1_mult = sblock.not() * m_1 - sblock.clone();
let wire_2_mult = LB::Expr::ZERO - sblock;
let wire_0 = AceWireMsg {
clk: ace_clk.into(),
ctx: ace_ctx.into(),
id: id_0.into(),
v0: v_0.0.into(),
v1: v_0.1.into(),
};
b.insert("wire_0", m_0, wire_0, Deg { v: 5, u: 5 });
let wire_1 = AceWireMsg {
clk: ace_clk.into(),
ctx: ace_ctx.into(),
id: id_1.into(),
v0: v_1.0.into(),
v1: v_1.1.into(),
};
b.insert("wire_1", wire_1_mult, wire_1, Deg { v: 6, u: 5 });
let wire_2 = AceWireMsg {
clk: ace_clk.into(),
ctx: ace_ctx.into(),
id: id_2.into(),
v0: v_2.0.into(),
v1: v_2.1.into(),
};
b.insert("wire_2", wire_2_mult, wire_2, Deg { v: 5, u: 5 });
},
Deg { v: 8, u: 7 }, );
g.add(
"perm_ctrl_input",
f_ctrl_input,
move || {
let state: [LB::Expr; 12] = ctrl_state.map(Into::into);
HasherPermLinkMsg::Input { state }
},
Deg { v: 2, u: 3 },
);
g.add(
"perm_ctrl_output",
f_ctrl_output,
move || {
let state: [LB::Expr; 12] = ctrl_state.map(Into::into);
HasherPermLinkMsg::Output { state }
},
Deg { v: 3, u: 4 },
);
let perm_mult_input: LB::Expr = LB::Expr::ZERO - perm_mult.into();
g.insert(
"perm_row0",
f_perm_row0,
perm_mult_input,
move || {
let state: [LB::Expr; 12] = perm_state.map(Into::into);
HasherPermLinkMsg::Input { state }
},
Deg { v: 3, u: 3 },
);
let perm_mult_output: LB::Expr = LB::Expr::ZERO - perm_mult.into();
g.insert(
"perm_row15",
f_perm_row15,
perm_mult_output,
move || {
let state: [LB::Expr; 12] = perm_state.map(Into::into);
HasherPermLinkMsg::Output { state }
},
Deg { v: 3, u: 3 },
);
},
Deg { v: 8, u: 7 },
);
},
Deg { v: 8, u: 7 },
);
}