openvm_circuit/system/memory/offline_checker/
columns.rs

1//! Defines auxiliary columns for memory operations: `MemoryReadAuxCols`,
2//! `MemoryReadWithImmediateAuxCols`, and `MemoryWriteAuxCols`.
3
4use openvm_circuit_primitives::is_less_than::LessThanAuxCols;
5use openvm_circuit_primitives_derive::AlignedBorrow;
6use openvm_stark_backend::p3_field::PrimeField32;
7
8use crate::system::memory::offline_checker::bridge::AUX_LEN;
9
10// repr(C) is needed to make sure that the compiler does not reorder the fields
11// we assume the order of the fields when using borrow or borrow_mut
12#[repr(C)]
13/// Base structure for auxiliary memory columns.
14#[derive(Clone, Copy, Debug, AlignedBorrow)]
15pub struct MemoryBaseAuxCols<T> {
16    /// The previous timestamps in which the cells were accessed.
17    pub(in crate::system::memory) prev_timestamp: T,
18    /// The auxiliary columns to perform the less than check.
19    pub(in crate::system::memory) timestamp_lt_aux: LessThanAuxCols<T, AUX_LEN>,
20}
21
22#[repr(C)]
23#[derive(Clone, Copy, Debug, AlignedBorrow)]
24pub struct MemoryWriteAuxCols<T, const N: usize> {
25    pub(in crate::system::memory) base: MemoryBaseAuxCols<T>,
26    pub(in crate::system::memory) prev_data: [T; N],
27}
28
29impl<const N: usize, T> MemoryWriteAuxCols<T, N> {
30    pub(in crate::system::memory) fn new(
31        prev_data: [T; N],
32        prev_timestamp: T,
33        lt_aux: LessThanAuxCols<T, AUX_LEN>,
34    ) -> Self {
35        Self {
36            base: MemoryBaseAuxCols {
37                prev_timestamp,
38                timestamp_lt_aux: lt_aux,
39            },
40            prev_data,
41        }
42    }
43}
44
45impl<const N: usize, T> MemoryWriteAuxCols<T, N> {
46    pub fn from_base(base: MemoryBaseAuxCols<T>, prev_data: [T; N]) -> Self {
47        Self { base, prev_data }
48    }
49
50    pub fn get_base(self) -> MemoryBaseAuxCols<T> {
51        self.base
52    }
53
54    pub fn prev_data(&self) -> &[T; N] {
55        &self.prev_data
56    }
57}
58
59/// The auxiliary columns for a memory read operation with block size `N`.
60/// These columns should be automatically managed by the memory controller.
61/// To fully constrain a memory read, in addition to these columns,
62/// the address space, pointer, and data must be provided.
63#[repr(C)]
64#[derive(Clone, Copy, Debug, AlignedBorrow)]
65pub struct MemoryReadAuxCols<T> {
66    pub(in crate::system::memory) base: MemoryBaseAuxCols<T>,
67}
68
69impl<F: PrimeField32> MemoryReadAuxCols<F> {
70    pub(in crate::system::memory) fn new(
71        prev_timestamp: u32,
72        timestamp_lt_aux: LessThanAuxCols<F, AUX_LEN>,
73    ) -> Self {
74        Self {
75            base: MemoryBaseAuxCols {
76                prev_timestamp: F::from_canonical_u32(prev_timestamp),
77                timestamp_lt_aux,
78            },
79        }
80    }
81
82    pub fn get_base(self) -> MemoryBaseAuxCols<F> {
83        self.base
84    }
85}
86
87#[repr(C)]
88#[derive(Clone, Debug, AlignedBorrow)]
89pub struct MemoryReadOrImmediateAuxCols<T> {
90    pub(crate) base: MemoryBaseAuxCols<T>,
91    pub(crate) is_immediate: T,
92    pub(crate) is_zero_aux: T,
93}
94
95impl<T, const N: usize> AsRef<MemoryReadAuxCols<T>> for MemoryWriteAuxCols<T, N> {
96    fn as_ref(&self) -> &MemoryReadAuxCols<T> {
97        // Safety:
98        //  - `MemoryReadAuxCols<T>` is repr(C) and its only field is the first field of `MemoryWriteAuxCols<T, N>`.
99        //  - Thus, the memory layout of `MemoryWriteAuxCols<T, N>` begins with a valid `MemoryReadAuxCols<T>`.
100        unsafe { &*(self as *const MemoryWriteAuxCols<T, N> as *const MemoryReadAuxCols<T>) }
101    }
102}