sp1_recursion_core/air/
memory.rs

1use p3_field::PrimeField32;
2use sp1_derive::AlignedBorrow;
3
4use crate::air::Block;
5
6#[derive(AlignedBorrow, Default, Debug, Clone)]
7#[repr(C)]
8pub struct MemoryInitCols<T> {
9    pub addr: T,
10    pub timestamp: T,
11    pub value: Block<T>,
12    pub is_initialize: T,
13    pub is_finalize: T,
14
15    /// This column is the least significant 16 bit limb of next_address - current_address.
16    pub diff_16bit_limb: T,
17
18    /// This column is the most significant 8 bit limb of next_address - current_address.
19    pub diff_12bit_limb: T,
20
21    /// Same for the address column.
22    pub addr_16bit_limb: T,
23    pub addr_12bit_limb: T,
24
25    // An additional column to indicate if the memory row is a padded row.
26    pub is_real: T,
27
28    // A flag column for when range checks need to be applied to the diff columns. Range checks
29    // always need to be applied to the address columns.
30    pub is_range_check: T,
31}
32
33impl<T: PrimeField32> MemoryInitCols<T> {
34    pub fn new() -> Self {
35        Self {
36            addr: T::zero(),
37            timestamp: T::zero(),
38            value: Block::from([T::zero(); 4]),
39            is_initialize: T::zero(),
40            is_finalize: T::zero(),
41            diff_16bit_limb: T::zero(),
42            diff_12bit_limb: T::zero(),
43            addr_16bit_limb: T::zero(),
44            addr_12bit_limb: T::zero(),
45            is_real: T::zero(),
46            is_range_check: T::zero(),
47        }
48    }
49}
50
51/// NOTE: These are very similar to core/src/memory/columns.rs
52/// The reason we cannot use those structs directly is that they use "shard".
53/// In our recursive VM, we don't have shards, we only have `clk` (i.e. timestamp).
54///
55/// Memory read access.
56#[derive(AlignedBorrow, Default, Debug, Clone, Copy)]
57#[repr(C)]
58pub struct MemoryReadCols<T> {
59    pub access: MemoryAccessCols<T, Block<T>>,
60}
61
62/// Memory read-write access.
63#[derive(AlignedBorrow, Default, Debug, Clone, Copy)]
64#[repr(C)]
65pub struct MemoryReadWriteCols<T> {
66    pub prev_value: Block<T>,
67    pub access: MemoryAccessCols<T, Block<T>>,
68}
69
70/// Memory read access of a single field element.
71#[derive(AlignedBorrow, Default, Debug, Clone, Copy)]
72#[repr(C)]
73pub struct MemoryReadSingleCols<T> {
74    pub access: MemoryAccessCols<T, T>,
75}
76
77/// Memory read-write access of a single field element.
78#[derive(AlignedBorrow, Default, Debug, Clone, Copy)]
79#[repr(C)]
80pub struct MemoryReadWriteSingleCols<T> {
81    pub prev_value: T,
82    pub access: MemoryAccessCols<T, T>,
83}
84
85#[derive(AlignedBorrow, Default, Debug, Clone, Copy)]
86#[repr(C)]
87pub struct MemoryAccessCols<T, TValue> {
88    /// The value of the memory access.
89    pub value: TValue,
90
91    /// The previous timestamp that this memory access is being read from.
92    pub prev_timestamp: T,
93
94    /// The following columns are decomposed limbs for the difference between the current access's
95    /// timestamp and the previous access's timestamp.  Note the actual value of the timestamp
96    /// is either the accesses' shard or clk depending on the value of compare_clk.
97    ///
98    /// This column is the least significant 16 bit limb of current access timestamp - prev access
99    /// timestamp.
100    pub diff_16bit_limb: T,
101
102    /// This column is the most significant 12 bit limb of current access timestamp - prev access
103    /// timestamp.
104    pub diff_12bit_limb: T,
105}
106
107/// The common columns for all memory access types.
108pub trait MemoryCols<T, TValue> {
109    fn access(&self) -> &MemoryAccessCols<T, TValue>;
110
111    fn access_mut(&mut self) -> &mut MemoryAccessCols<T, TValue>;
112
113    fn prev_value(&self) -> &TValue;
114
115    fn prev_value_mut(&mut self) -> &mut TValue;
116
117    fn value(&self) -> &TValue;
118
119    fn value_mut(&mut self) -> &mut TValue;
120}
121
122pub trait MemoryAccessTimestampCols<T> {
123    fn prev_timestamp(&self) -> &T;
124
125    fn diff_16bit_limb(&self) -> &T;
126
127    fn diff_12bit_limb(&self) -> &T;
128}
129
130impl<T> MemoryAccessTimestampCols<T> for MemoryAccessCols<T, Block<T>> {
131    fn prev_timestamp(&self) -> &T {
132        &self.prev_timestamp
133    }
134
135    fn diff_16bit_limb(&self) -> &T {
136        &self.diff_16bit_limb
137    }
138
139    fn diff_12bit_limb(&self) -> &T {
140        &self.diff_12bit_limb
141    }
142}
143
144impl<T> MemoryAccessTimestampCols<T> for MemoryAccessCols<T, T> {
145    fn prev_timestamp(&self) -> &T {
146        &self.prev_timestamp
147    }
148
149    fn diff_16bit_limb(&self) -> &T {
150        &self.diff_16bit_limb
151    }
152
153    fn diff_12bit_limb(&self) -> &T {
154        &self.diff_12bit_limb
155    }
156}
157
158impl<T> MemoryCols<T, Block<T>> for MemoryReadCols<T> {
159    fn access(&self) -> &MemoryAccessCols<T, Block<T>> {
160        &self.access
161    }
162
163    fn access_mut(&mut self) -> &mut MemoryAccessCols<T, Block<T>> {
164        &mut self.access
165    }
166
167    fn prev_value(&self) -> &Block<T> {
168        &self.access.value
169    }
170
171    fn prev_value_mut(&mut self) -> &mut Block<T> {
172        &mut self.access.value
173    }
174
175    fn value(&self) -> &Block<T> {
176        &self.access.value
177    }
178
179    fn value_mut(&mut self) -> &mut Block<T> {
180        &mut self.access.value
181    }
182}
183
184impl<T> MemoryCols<T, Block<T>> for MemoryReadWriteCols<T> {
185    fn access(&self) -> &MemoryAccessCols<T, Block<T>> {
186        &self.access
187    }
188
189    fn access_mut(&mut self) -> &mut MemoryAccessCols<T, Block<T>> {
190        &mut self.access
191    }
192
193    fn prev_value(&self) -> &Block<T> {
194        &self.prev_value
195    }
196
197    fn prev_value_mut(&mut self) -> &mut Block<T> {
198        &mut self.prev_value
199    }
200
201    fn value(&self) -> &Block<T> {
202        &self.access.value
203    }
204
205    fn value_mut(&mut self) -> &mut Block<T> {
206        &mut self.access.value
207    }
208}
209
210impl<T> MemoryCols<T, T> for MemoryReadSingleCols<T> {
211    fn access(&self) -> &MemoryAccessCols<T, T> {
212        &self.access
213    }
214
215    fn access_mut(&mut self) -> &mut MemoryAccessCols<T, T> {
216        &mut self.access
217    }
218
219    fn prev_value(&self) -> &T {
220        &self.access.value
221    }
222
223    fn prev_value_mut(&mut self) -> &mut T {
224        &mut self.access.value
225    }
226
227    fn value(&self) -> &T {
228        &self.access.value
229    }
230
231    fn value_mut(&mut self) -> &mut T {
232        &mut self.access.value
233    }
234}
235
236impl<T> MemoryCols<T, T> for MemoryReadWriteSingleCols<T> {
237    fn access(&self) -> &MemoryAccessCols<T, T> {
238        &self.access
239    }
240
241    fn access_mut(&mut self) -> &mut MemoryAccessCols<T, T> {
242        &mut self.access
243    }
244
245    fn prev_value(&self) -> &T {
246        &self.prev_value
247    }
248
249    fn prev_value_mut(&mut self) -> &mut T {
250        &mut self.prev_value
251    }
252
253    fn value(&self) -> &T {
254        &self.access.value
255    }
256
257    fn value_mut(&mut self) -> &mut T {
258        &mut self.access.value
259    }
260}