1use alloc::{string::ToString, vec::Vec};
2use core::slice;
3
4use miden_air::trace::MainTrace;
5
6use super::chiplets::Chiplets;
7use crate::{Felt, RowIndex, debug::BusDebugger, field::ExtensionField, utils::uninit_vector};
8#[cfg(test)]
9use crate::{operation::Operation, utils::ToElements};
10
11pub struct TraceFragment<'a> {
16 data: Vec<&'a mut [Felt]>,
17 num_rows: usize,
18}
19
20impl<'a> TraceFragment<'a> {
21 pub fn new(num_columns: usize, num_rows: usize) -> Self {
25 TraceFragment {
26 data: Vec::with_capacity(num_columns),
27 num_rows,
28 }
29 }
30
31 pub fn width(&self) -> usize {
36 self.data.len()
37 }
38
39 pub fn len(&self) -> usize {
41 self.num_rows
42 }
43
44 #[inline(always)]
49 pub fn set(&mut self, row_idx: RowIndex, col_idx: usize, value: Felt) {
50 self.data[col_idx][row_idx] = value;
51 }
52
53 pub fn columns(&mut self) -> slice::IterMut<'_, &'a mut [Felt]> {
55 self.data.iter_mut()
56 }
57
58 pub fn push_column_slice(&mut self, column: &'a mut [Felt]) -> &'a mut [Felt] {
63 let (column_fragment, rest) = column.split_at_mut(self.num_rows);
64 self.data.push(column_fragment);
65 rest
66 }
67
68 #[cfg(test)]
72 pub fn trace_to_fragment(trace: &'a mut [Vec<Felt>]) -> Self {
73 assert!(!trace.is_empty(), "expected trace to have at least one column");
74 let mut data = Vec::new();
75 for column in trace.iter_mut() {
76 data.push(column.as_mut_slice());
77 }
78
79 let num_rows = data[0].len();
80 Self { data, num_rows }
81 }
82}
83
84#[derive(Debug, Default, Eq, PartialEq, Clone, Copy)]
94pub struct TraceLenSummary {
95 main_trace_len: usize,
96 range_trace_len: usize,
97 chiplets_trace_len: ChipletsLengths,
98}
99
100impl TraceLenSummary {
101 pub fn new(
102 main_trace_len: usize,
103 range_trace_len: usize,
104 chiplets_trace_len: ChipletsLengths,
105 ) -> Self {
106 TraceLenSummary {
107 main_trace_len,
108 range_trace_len,
109 chiplets_trace_len,
110 }
111 }
112
113 pub fn main_trace_len(&self) -> usize {
115 self.main_trace_len
116 }
117
118 pub fn range_trace_len(&self) -> usize {
120 self.range_trace_len
121 }
122
123 pub fn chiplets_trace_len(&self) -> ChipletsLengths {
125 self.chiplets_trace_len
126 }
127
128 pub fn trace_len(&self) -> usize {
130 self.range_trace_len
131 .max(self.main_trace_len)
132 .max(self.chiplets_trace_len.trace_len())
133 }
134
135 pub fn padded_trace_len(&self) -> usize {
137 self.trace_len().next_power_of_two()
138 }
139
140 pub fn padding_percentage(&self) -> usize {
143 (self.padded_trace_len() - self.trace_len()) * 100 / self.padded_trace_len()
144 }
145}
146
147#[derive(Default, Clone, Copy, Debug, PartialEq, Eq)]
153pub struct ChipletsLengths {
154 hash_chiplet_len: usize,
155 bitwise_chiplet_len: usize,
156 memory_chiplet_len: usize,
157 kernel_rom_len: usize,
158}
159
160impl ChipletsLengths {
161 pub fn new(chiplets: &Chiplets) -> Self {
162 ChipletsLengths {
163 hash_chiplet_len: chiplets.bitwise_start().into(),
164 bitwise_chiplet_len: chiplets.memory_start() - chiplets.bitwise_start(),
165 memory_chiplet_len: chiplets.kernel_rom_start() - chiplets.memory_start(),
166 kernel_rom_len: chiplets.padding_start() - chiplets.kernel_rom_start(),
167 }
168 }
169
170 pub fn from_parts(
171 hash_len: usize,
172 bitwise_len: usize,
173 memory_len: usize,
174 kernel_len: usize,
175 ) -> Self {
176 ChipletsLengths {
177 hash_chiplet_len: hash_len,
178 bitwise_chiplet_len: bitwise_len,
179 memory_chiplet_len: memory_len,
180 kernel_rom_len: kernel_len,
181 }
182 }
183
184 pub fn hash_chiplet_len(&self) -> usize {
186 self.hash_chiplet_len
187 }
188
189 pub fn bitwise_chiplet_len(&self) -> usize {
191 self.bitwise_chiplet_len
192 }
193
194 pub fn memory_chiplet_len(&self) -> usize {
196 self.memory_chiplet_len
197 }
198
199 pub fn kernel_rom_len(&self) -> usize {
201 self.kernel_rom_len
202 }
203
204 pub fn trace_len(&self) -> usize {
208 self.hash_chiplet_len()
209 + self.bitwise_chiplet_len()
210 + self.memory_chiplet_len()
211 + self.kernel_rom_len()
212 + 1
213 }
214}
215
216pub(crate) trait AuxColumnBuilder<E: ExtensionField<Felt>> {
222 fn get_requests_at(
226 &self,
227 main_trace: &MainTrace,
228 alphas: &[E],
229 row: RowIndex,
230 debugger: &mut BusDebugger<E>,
231 ) -> E;
232
233 fn get_responses_at(
234 &self,
235 main_trace: &MainTrace,
236 alphas: &[E],
237 row: RowIndex,
238 debugger: &mut BusDebugger<E>,
239 ) -> E;
240
241 fn init_requests(
245 &self,
246 _main_trace: &MainTrace,
247 _alphas: &[E],
248 _debugger: &mut BusDebugger<E>,
249 ) -> E {
250 E::ONE
251 }
252
253 fn init_responses(
254 &self,
255 _main_trace: &MainTrace,
256 _alphas: &[E],
257 _debugger: &mut BusDebugger<E>,
258 ) -> E {
259 E::ONE
260 }
261
262 fn build_aux_column(&self, main_trace: &MainTrace, alphas: &[E]) -> Vec<E> {
264 let mut bus_debugger = BusDebugger::new("chiplets bus".to_string());
265
266 let mut requests: Vec<E> = unsafe { uninit_vector(main_trace.num_rows()) };
267 requests[0] = self.init_requests(main_trace, alphas, &mut bus_debugger);
268
269 let mut responses_prod: Vec<E> = unsafe { uninit_vector(main_trace.num_rows()) };
270 responses_prod[0] = self.init_responses(main_trace, alphas, &mut bus_debugger);
271
272 let mut requests_running_prod = requests[0];
273
274 for row_idx in 0..main_trace.num_rows() - 1 {
276 let row = row_idx.into();
277
278 let response = self.get_responses_at(main_trace, alphas, row, &mut bus_debugger);
279 responses_prod[row_idx + 1] = responses_prod[row_idx] * response;
280
281 let request = self.get_requests_at(main_trace, alphas, row, &mut bus_debugger);
282 requests[row_idx + 1] = request;
283 requests_running_prod *= request;
284 }
285
286 let mut result_aux_column = responses_prod;
288 let mut requests_running_divisor = requests_running_prod.inverse();
289 for i in (0..main_trace.num_rows()).rev() {
290 result_aux_column[i] *= requests_running_divisor;
291 requests_running_divisor *= requests[i];
292 }
293
294 #[cfg(any(test, feature = "bus-debugger"))]
295 assert!(bus_debugger.is_empty(), "{bus_debugger}");
296
297 result_aux_column
298 }
299}
300
301pub(crate) fn split_element_u32_into_u16(value: Felt) -> (Felt, Felt) {
307 let (hi, lo) = split_u32_into_u16(value.as_canonical_u64());
308 (Felt::new(hi as u64), Felt::new(lo as u64))
309}
310
311pub(crate) fn split_u32_into_u16(value: u64) -> (u16, u16) {
316 const U32MAX: u64 = u32::MAX as u64;
317 debug_assert!(value <= U32MAX, "not a 32-bit value");
318
319 let lo = value as u16;
320 let hi = (value >> 16) as u16;
321
322 (hi, lo)
323}
324
325#[cfg(test)]
329pub fn build_span_with_respan_ops() -> (Vec<Operation>, Vec<Felt>) {
330 let iv = [1, 3, 5, 7, 9, 11, 13, 15, 17].to_elements();
331 let ops = vec![
332 Operation::Push(iv[0]),
333 Operation::Push(iv[1]),
334 Operation::Push(iv[2]),
335 Operation::Push(iv[3]),
336 Operation::Push(iv[4]),
337 Operation::Push(iv[5]),
338 Operation::Push(iv[6]),
339 Operation::Push(iv[7]),
341 Operation::Push(iv[8]),
342 Operation::Add,
343 Operation::Drop,
345 Operation::Drop,
346 Operation::Drop,
347 Operation::Drop,
348 Operation::Drop,
349 Operation::Drop,
350 Operation::Drop,
351 Operation::Drop,
352 ];
353 (ops, iv)
354}