1use alloc::{string::ToString, vec::Vec};
2use core::slice;
3
4use miden_air::trace::MainTrace;
5
6use super::chiplets::Chiplets;
7use crate::{
8 Felt, RowIndex,
9 debug::BusDebugger,
10 field::{ExtensionField, PrimeField64},
11 utils::uninit_vector,
12};
13#[cfg(test)]
14use crate::{operation::Operation, utils::ToElements};
15
16pub struct TraceFragment<'a> {
21 data: Vec<&'a mut [Felt]>,
22 num_rows: usize,
23}
24
25impl<'a> TraceFragment<'a> {
26 pub fn new(num_columns: usize, num_rows: usize) -> Self {
30 TraceFragment {
31 data: Vec::with_capacity(num_columns),
32 num_rows,
33 }
34 }
35
36 pub fn width(&self) -> usize {
41 self.data.len()
42 }
43
44 pub fn len(&self) -> usize {
46 self.num_rows
47 }
48
49 #[inline(always)]
54 pub fn set(&mut self, row_idx: RowIndex, col_idx: usize, value: Felt) {
55 self.data[col_idx][row_idx] = value;
56 }
57
58 pub fn columns(&mut self) -> slice::IterMut<'_, &'a mut [Felt]> {
60 self.data.iter_mut()
61 }
62
63 pub fn push_column_slice(&mut self, column: &'a mut [Felt]) -> &'a mut [Felt] {
68 let (column_fragment, rest) = column.split_at_mut(self.num_rows);
69 self.data.push(column_fragment);
70 rest
71 }
72
73 #[cfg(test)]
77 pub fn trace_to_fragment(trace: &'a mut [Vec<Felt>]) -> Self {
78 assert!(!trace.is_empty(), "expected trace to have at least one column");
79 let mut data = Vec::new();
80 for column in trace.iter_mut() {
81 data.push(column.as_mut_slice());
82 }
83
84 let num_rows = data[0].len();
85 Self { data, num_rows }
86 }
87}
88
89#[derive(Debug, Default, Eq, PartialEq, Clone, Copy)]
99pub struct TraceLenSummary {
100 main_trace_len: usize,
101 range_trace_len: usize,
102 chiplets_trace_len: ChipletsLengths,
103}
104
105impl TraceLenSummary {
106 pub fn new(
107 main_trace_len: usize,
108 range_trace_len: usize,
109 chiplets_trace_len: ChipletsLengths,
110 ) -> Self {
111 TraceLenSummary {
112 main_trace_len,
113 range_trace_len,
114 chiplets_trace_len,
115 }
116 }
117
118 pub fn main_trace_len(&self) -> usize {
120 self.main_trace_len
121 }
122
123 pub fn range_trace_len(&self) -> usize {
125 self.range_trace_len
126 }
127
128 pub fn chiplets_trace_len(&self) -> ChipletsLengths {
130 self.chiplets_trace_len
131 }
132
133 pub fn trace_len(&self) -> usize {
135 self.range_trace_len
136 .max(self.main_trace_len)
137 .max(self.chiplets_trace_len.trace_len())
138 }
139
140 pub fn padded_trace_len(&self) -> usize {
142 self.trace_len().next_power_of_two()
143 }
144
145 pub fn padding_percentage(&self) -> usize {
148 (self.padded_trace_len() - self.trace_len()) * 100 / self.padded_trace_len()
149 }
150}
151
152#[derive(Default, Clone, Copy, Debug, PartialEq, Eq)]
158pub struct ChipletsLengths {
159 hash_chiplet_len: usize,
160 bitwise_chiplet_len: usize,
161 memory_chiplet_len: usize,
162 kernel_rom_len: usize,
163}
164
165impl ChipletsLengths {
166 pub fn new(chiplets: &Chiplets) -> Self {
167 ChipletsLengths {
168 hash_chiplet_len: chiplets.bitwise_start().into(),
169 bitwise_chiplet_len: chiplets.memory_start() - chiplets.bitwise_start(),
170 memory_chiplet_len: chiplets.kernel_rom_start() - chiplets.memory_start(),
171 kernel_rom_len: chiplets.padding_start() - chiplets.kernel_rom_start(),
172 }
173 }
174
175 pub fn from_parts(
176 hash_len: usize,
177 bitwise_len: usize,
178 memory_len: usize,
179 kernel_len: usize,
180 ) -> Self {
181 ChipletsLengths {
182 hash_chiplet_len: hash_len,
183 bitwise_chiplet_len: bitwise_len,
184 memory_chiplet_len: memory_len,
185 kernel_rom_len: kernel_len,
186 }
187 }
188
189 pub fn hash_chiplet_len(&self) -> usize {
191 self.hash_chiplet_len
192 }
193
194 pub fn bitwise_chiplet_len(&self) -> usize {
196 self.bitwise_chiplet_len
197 }
198
199 pub fn memory_chiplet_len(&self) -> usize {
201 self.memory_chiplet_len
202 }
203
204 pub fn kernel_rom_len(&self) -> usize {
206 self.kernel_rom_len
207 }
208
209 pub fn trace_len(&self) -> usize {
213 self.hash_chiplet_len()
214 + self.bitwise_chiplet_len()
215 + self.memory_chiplet_len()
216 + self.kernel_rom_len()
217 + 1
218 }
219}
220
221pub(crate) trait AuxColumnBuilder<E: ExtensionField<Felt>> {
227 fn get_requests_at(
231 &self,
232 main_trace: &MainTrace,
233 alphas: &[E],
234 row: RowIndex,
235 debugger: &mut BusDebugger<E>,
236 ) -> E;
237
238 fn get_responses_at(
239 &self,
240 main_trace: &MainTrace,
241 alphas: &[E],
242 row: RowIndex,
243 debugger: &mut BusDebugger<E>,
244 ) -> E;
245
246 fn init_requests(
250 &self,
251 _main_trace: &MainTrace,
252 _alphas: &[E],
253 _debugger: &mut BusDebugger<E>,
254 ) -> E {
255 E::ONE
256 }
257
258 fn init_responses(
259 &self,
260 _main_trace: &MainTrace,
261 _alphas: &[E],
262 _debugger: &mut BusDebugger<E>,
263 ) -> E {
264 E::ONE
265 }
266
267 fn build_aux_column(&self, main_trace: &MainTrace, alphas: &[E]) -> Vec<E> {
269 let mut bus_debugger = BusDebugger::new("chiplets bus".to_string());
270
271 let mut requests: Vec<E> = unsafe { uninit_vector(main_trace.num_rows()) };
272 requests[0] = self.init_requests(main_trace, alphas, &mut bus_debugger);
273
274 let mut responses_prod: Vec<E> = unsafe { uninit_vector(main_trace.num_rows()) };
275 responses_prod[0] = self.init_responses(main_trace, alphas, &mut bus_debugger);
276
277 let mut requests_running_prod = requests[0];
278
279 for row_idx in 0..main_trace.num_rows() - 1 {
281 let row = row_idx.into();
282
283 let response = self.get_responses_at(main_trace, alphas, row, &mut bus_debugger);
284 responses_prod[row_idx + 1] = responses_prod[row_idx] * response;
285
286 let request = self.get_requests_at(main_trace, alphas, row, &mut bus_debugger);
287 requests[row_idx + 1] = request;
288 requests_running_prod *= request;
289 }
290
291 let mut result_aux_column = responses_prod;
293 let mut requests_running_divisor = requests_running_prod.inverse();
294 for i in (0..main_trace.num_rows()).rev() {
295 result_aux_column[i] *= requests_running_divisor;
296 requests_running_divisor *= requests[i];
297 }
298
299 #[cfg(any(test, feature = "bus-debugger"))]
300 assert!(bus_debugger.is_empty(), "{bus_debugger}");
301
302 result_aux_column
303 }
304}
305
306pub(crate) fn split_element_u32_into_u16(value: Felt) -> (Felt, Felt) {
312 let (hi, lo) = split_u32_into_u16(value.as_canonical_u64());
313 (Felt::new(hi as u64), Felt::new(lo as u64))
314}
315
316pub(crate) fn split_u32_into_u16(value: u64) -> (u16, u16) {
321 const U32MAX: u64 = u32::MAX as u64;
322 debug_assert!(value <= U32MAX, "not a 32-bit value");
323
324 let lo = value as u16;
325 let hi = (value >> 16) as u16;
326
327 (hi, lo)
328}
329
330#[cfg(test)]
334pub fn build_span_with_respan_ops() -> (Vec<Operation>, Vec<Felt>) {
335 let iv = [1, 3, 5, 7, 9, 11, 13, 15, 17].to_elements();
336 let ops = vec![
337 Operation::Push(iv[0]),
338 Operation::Push(iv[1]),
339 Operation::Push(iv[2]),
340 Operation::Push(iv[3]),
341 Operation::Push(iv[4]),
342 Operation::Push(iv[5]),
343 Operation::Push(iv[6]),
344 Operation::Push(iv[7]),
346 Operation::Push(iv[8]),
347 Operation::Add,
348 Operation::Drop,
350 Operation::Drop,
351 Operation::Drop,
352 Operation::Drop,
353 Operation::Drop,
354 Operation::Drop,
355 Operation::Drop,
356 Operation::Drop,
357 ];
358 (ops, iv)
359}