use alloc::{vec, vec::Vec};
use core::{
borrow::{Borrow, BorrowMut},
mem::size_of,
};
use miden_core::{Felt, WORD_SIZE, field::PrimeCharacteristicRing};
use super::super::{columns::indices_arr, ext_field::QuadFeltExpr};
use crate::trace::chiplets::{
bitwise::NUM_DECOMP_BITS,
hasher::{CAPACITY_LEN, DIGEST_LEN, RATE_LEN, STATE_WIDTH, TRACE_WIDTH},
};
macro_rules! impl_borrow_for_chiplet_cols {
($cols:ident) => {
impl<T> Borrow<$cols<T>> for [T] {
fn borrow(&self) -> &$cols<T> {
debug_assert_eq!(self.len(), size_of::<$cols<u8>>());
let (prefix, cols, suffix) = unsafe { self.align_to::<$cols<T>>() };
debug_assert!(prefix.is_empty() && suffix.is_empty() && cols.len() == 1);
&cols[0]
}
}
impl<T> BorrowMut<$cols<T>> for [T] {
fn borrow_mut(&mut self) -> &mut $cols<T> {
debug_assert_eq!(self.len(), size_of::<$cols<u8>>());
let (prefix, cols, suffix) = unsafe { self.align_to_mut::<$cols<T>>() };
debug_assert!(prefix.is_empty() && suffix.is_empty() && cols.len() == 1);
&mut cols[0]
}
}
};
}
#[repr(C)]
#[derive(Clone, Debug)]
pub struct ControllerCols<T> {
pub s0: T,
pub s1: T,
pub s2: T,
pub state: [T; STATE_WIDTH],
pub node_index: T,
pub mrupdate_id: T,
pub is_boundary: T,
pub direction_bit: T,
pub perm_id: T,
}
impl<T: Copy> ControllerCols<T> {
pub fn rate(&self) -> [T; RATE_LEN] {
[
self.state[0],
self.state[1],
self.state[2],
self.state[3],
self.state[4],
self.state[5],
self.state[6],
self.state[7],
]
}
pub fn capacity(&self) -> [T; CAPACITY_LEN] {
[self.state[8], self.state[9], self.state[10], self.state[11]]
}
pub fn digest(&self) -> [T; DIGEST_LEN] {
[self.state[0], self.state[1], self.state[2], self.state[3]]
}
pub fn rate0(&self) -> [T; DIGEST_LEN] {
[self.state[0], self.state[1], self.state[2], self.state[3]]
}
pub fn rate1(&self) -> [T; DIGEST_LEN] {
[self.state[4], self.state[5], self.state[6], self.state[7]]
}
pub fn f_mu<E: PrimeCharacteristicRing>(&self) -> E
where
T: Into<E>,
{
self.s0.into() * self.s1.into() * self.s2.into()
}
pub fn f_mv<E: PrimeCharacteristicRing>(&self) -> E
where
T: Into<E>,
{
self.s0.into() * self.s1.into() * (E::ONE - self.s2.into())
}
}
#[repr(C)]
#[derive(Clone, Debug)]
pub struct BitwiseCols<T> {
pub op_flag: T,
pub a: T,
pub b: T,
pub a_bits: [T; NUM_DECOMP_BITS],
pub b_bits: [T; NUM_DECOMP_BITS],
pub prev_output: T,
pub output: T,
}
#[repr(C)]
#[derive(Clone, Debug)]
pub struct MemoryCols<T> {
pub is_read: T,
pub is_word: T,
pub ctx: T,
pub word_addr: T,
pub idx0: T,
pub idx1: T,
pub clk: T,
pub values: [T; WORD_SIZE],
pub d0: T,
pub d1: T,
pub d_inv: T,
pub is_same_ctx_and_addr: T,
}
#[repr(C)]
#[derive(Clone, Debug)]
pub struct AceCols<T> {
pub s_start: T,
pub s_block: T,
pub ctx: T,
pub ptr: T,
pub clk: T,
pub eval_op: T,
pub id_0: T,
pub v_0: QuadFeltExpr<T>,
pub id_1: T,
pub v_1: QuadFeltExpr<T>,
mode: [T; 4],
}
impl<T> AceCols<T> {
pub fn read(&self) -> &AceReadCols<T> {
self.mode.as_slice().borrow()
}
pub fn eval(&self) -> &AceEvalCols<T> {
self.mode.as_slice().borrow()
}
pub fn read_mut(&mut self) -> &mut AceReadCols<T> {
self.mode.as_mut_slice().borrow_mut()
}
pub fn eval_mut(&mut self) -> &mut AceEvalCols<T> {
self.mode.as_mut_slice().borrow_mut()
}
}
impl<T: Copy> AceCols<T> {
pub fn f_read<E: PrimeCharacteristicRing>(&self) -> E
where
T: Into<E>,
{
E::ONE - self.s_block.into()
}
pub fn f_eval<E: PrimeCharacteristicRing>(&self) -> E
where
T: Into<E>,
{
self.s_block.into()
}
}
#[repr(C)]
#[derive(Clone, Debug)]
pub struct AceReadCols<T> {
pub num_eval: T,
pub unused: T,
pub m_1: T,
pub m_0: T,
}
#[repr(C)]
#[derive(Clone, Debug)]
pub struct AceEvalCols<T> {
pub id_2: T,
pub v_2: QuadFeltExpr<T>,
pub m_0: T,
}
#[allow(dead_code)]
pub const ACE_COL_MAP: AceCols<usize> = {
assert!(size_of::<AceCols<u8>>() == 16);
unsafe { core::mem::transmute(indices_arr::<{ size_of::<AceCols<u8>>() }>()) }
};
pub const ACE_READ_COL_MAP: AceReadCols<usize> = {
assert!(size_of::<AceReadCols<u8>>() == 4);
unsafe { core::mem::transmute(indices_arr::<{ size_of::<AceReadCols<u8>>() }>()) }
};
pub const ACE_EVAL_COL_MAP: AceEvalCols<usize> = {
assert!(size_of::<AceEvalCols<u8>>() == 4);
unsafe { core::mem::transmute(indices_arr::<{ size_of::<AceEvalCols<u8>>() }>()) }
};
#[allow(dead_code)]
pub const MODE_OFFSET: usize = ACE_COL_MAP.mode[0];
const _: () = {
assert!(size_of::<AceCols<u8>>() == 16);
assert!(size_of::<AceReadCols<u8>>() == 4);
assert!(size_of::<AceEvalCols<u8>>() == 4);
assert!(ACE_READ_COL_MAP.m_0 == ACE_EVAL_COL_MAP.m_0);
assert!(ACE_READ_COL_MAP.num_eval == ACE_EVAL_COL_MAP.id_2);
assert!(ACE_READ_COL_MAP.m_1 == ACE_EVAL_COL_MAP.v_2.1);
};
#[repr(C)]
#[derive(Clone, Debug)]
pub struct KernelRomCols<T> {
pub multiplicity: T,
pub root: [T; WORD_SIZE],
}
#[derive(Clone, Copy)]
#[repr(C)]
pub struct PeriodicCols<T> {
pub bitwise: BitwisePeriodicCols<T>,
}
#[derive(Clone, Copy)]
#[repr(C)]
pub struct BitwisePeriodicCols<T> {
pub k_first: T,
pub k_transition: T,
}
impl Default for BitwisePeriodicCols<Vec<Felt>> {
fn default() -> Self {
Self::new()
}
}
impl BitwisePeriodicCols<Vec<Felt>> {
pub fn new() -> Self {
let k_first = vec![
Felt::ONE,
Felt::ZERO,
Felt::ZERO,
Felt::ZERO,
Felt::ZERO,
Felt::ZERO,
Felt::ZERO,
Felt::ZERO,
];
let k_transition = vec![
Felt::ONE,
Felt::ONE,
Felt::ONE,
Felt::ONE,
Felt::ONE,
Felt::ONE,
Felt::ONE,
Felt::ZERO,
];
Self { k_first, k_transition }
}
pub fn periodic_columns() -> Vec<Vec<Felt>> {
let BitwisePeriodicCols { k_first, k_transition } = Self::new();
vec![k_first, k_transition]
}
}
impl PeriodicCols<Vec<Felt>> {
pub fn periodic_columns() -> Vec<Vec<Felt>> {
BitwisePeriodicCols::periodic_columns()
}
}
pub const NUM_PERIODIC_COLUMNS: usize = size_of::<PeriodicCols<u8>>();
impl<T> Borrow<PeriodicCols<T>> for [T] {
fn borrow(&self) -> &PeriodicCols<T> {
debug_assert_eq!(self.len(), NUM_PERIODIC_COLUMNS);
let (prefix, cols, suffix) = unsafe { self.align_to::<PeriodicCols<T>>() };
debug_assert!(prefix.is_empty() && suffix.is_empty() && cols.len() == 1);
&cols[0]
}
}
const _: () = {
assert!(size_of::<PeriodicCols<u8>>() == 2);
assert!(size_of::<BitwisePeriodicCols<u8>>() == 2);
assert!(size_of::<ControllerCols<u8>>() == TRACE_WIDTH);
};
impl_borrow_for_chiplet_cols!(ControllerCols);
impl_borrow_for_chiplet_cols!(BitwiseCols);
impl_borrow_for_chiplet_cols!(MemoryCols);
impl_borrow_for_chiplet_cols!(AceCols);
impl_borrow_for_chiplet_cols!(AceReadCols);
impl_borrow_for_chiplet_cols!(AceEvalCols);
impl_borrow_for_chiplet_cols!(KernelRomCols);
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn periodic_columns_dimensions() {
let cols = PeriodicCols::periodic_columns();
assert_eq!(cols.len(), NUM_PERIODIC_COLUMNS);
for col in &cols {
assert_eq!(col.len(), 8);
}
}
}