// TODO: remove when possible. #![allow(dead_code)] use std::borrow::{Borrow, BorrowMut}; use std::fmt::Debug; use std::mem::{size_of, transmute}; use std::ops::{Index, IndexMut}; use plonky2::field::types::Field; use crate::cpu::columns::general::CpuGeneralColumnsView; use crate::cpu::columns::ops::OpsColumnsView; use crate::cpu::membus::NUM_GP_CHANNELS; use crate::memory; use crate::util::{indices_arr, transmute_no_compile_time_size_checks}; mod general; pub(crate) mod ops; pub type MemValue = [T; memory::VALUE_LIMBS]; #[repr(C)] #[derive(Clone, Copy, Debug, Eq, PartialEq)] pub struct MemoryChannelView { /// 1 if this row includes a memory operation in the `i`th channel of the memory bus, otherwise /// 0. pub used: T, pub is_read: T, pub addr_context: T, pub addr_segment: T, pub addr_virtual: T, pub value: MemValue, } #[repr(C)] #[derive(Clone, Copy, Eq, PartialEq, Debug)] pub struct CpuColumnsView { /// Filter. 1 if the row is part of bootstrapping the kernel code, 0 otherwise. pub is_bootstrap_kernel: T, /// Filter. 1 if the row corresponds to a cycle of execution and 0 otherwise. /// Lets us re-use columns in non-cycle rows. pub is_cpu_cycle: T, /// If CPU cycle: Current context. // TODO: this is currently unconstrained pub context: T, /// If CPU cycle: Context for code memory channel. pub code_context: T, /// If CPU cycle: The program counter for the current instruction. pub program_counter: T, /// If CPU cycle: The stack length. pub stack_len: T, /// If CPU cycle: A prover-provided value needed to show that the instruction does not cause the /// stack to underflow or overflow. pub stack_len_bounds_aux: T, /// If CPU cycle: We're in kernel (privileged) mode. pub is_kernel_mode: T, /// If CPU cycle: flags for EVM instructions (a few cannot be shared; see the comments in /// `OpsColumnsView`). pub op: OpsColumnsView, /// If CPU cycle: the opcode, broken up into bits in little-endian order. pub opcode_bits: [T; 8], /// Filter. 1 iff a Keccak sponge lookup is performed on this row. pub is_keccak_sponge: T, pub(crate) general: CpuGeneralColumnsView, pub(crate) clock: T, pub mem_channels: [MemoryChannelView; NUM_GP_CHANNELS], } // `u8` is guaranteed to have a `size_of` of 1. pub const NUM_CPU_COLUMNS: usize = size_of::>(); impl Default for CpuColumnsView { fn default() -> Self { Self::from([F::ZERO; NUM_CPU_COLUMNS]) } } impl From<[T; NUM_CPU_COLUMNS]> for CpuColumnsView { fn from(value: [T; NUM_CPU_COLUMNS]) -> Self { unsafe { transmute_no_compile_time_size_checks(value) } } } impl From> for [T; NUM_CPU_COLUMNS] { fn from(value: CpuColumnsView) -> Self { unsafe { transmute_no_compile_time_size_checks(value) } } } impl Borrow> for [T; NUM_CPU_COLUMNS] { fn borrow(&self) -> &CpuColumnsView { unsafe { transmute(self) } } } impl BorrowMut> for [T; NUM_CPU_COLUMNS] { fn borrow_mut(&mut self) -> &mut CpuColumnsView { unsafe { transmute(self) } } } impl Borrow<[T; NUM_CPU_COLUMNS]> for CpuColumnsView { fn borrow(&self) -> &[T; NUM_CPU_COLUMNS] { unsafe { transmute(self) } } } impl BorrowMut<[T; NUM_CPU_COLUMNS]> for CpuColumnsView { fn borrow_mut(&mut self) -> &mut [T; NUM_CPU_COLUMNS] { unsafe { transmute(self) } } } impl Index for CpuColumnsView where [T]: Index, { type Output = <[T] as Index>::Output; fn index(&self, index: I) -> &Self::Output { let arr: &[T; NUM_CPU_COLUMNS] = self.borrow(); <[T] as Index>::index(arr, index) } } impl IndexMut for CpuColumnsView where [T]: IndexMut, { fn index_mut(&mut self, index: I) -> &mut Self::Output { let arr: &mut [T; NUM_CPU_COLUMNS] = self.borrow_mut(); <[T] as IndexMut>::index_mut(arr, index) } } const fn make_col_map() -> CpuColumnsView { let indices_arr = indices_arr::(); unsafe { transmute::<[usize; NUM_CPU_COLUMNS], CpuColumnsView>(indices_arr) } } pub const COL_MAP: CpuColumnsView = make_col_map();