sp1_core_machine/bytes/
trace.rs

1use std::borrow::BorrowMut;
2
3use p3_field::PrimeField32;
4use p3_matrix::dense::RowMajorMatrix;
5use sp1_core_executor::{ByteOpcode, ExecutionRecord, Program};
6use sp1_stark::air::MachineAir;
7
8use crate::utils::zeroed_f_vec;
9
10use super::{
11    columns::{ByteMultCols, NUM_BYTE_MULT_COLS, NUM_BYTE_PREPROCESSED_COLS},
12    ByteChip,
13};
14
15pub const NUM_ROWS: usize = 1 << 16;
16
17impl<F: PrimeField32> MachineAir<F> for ByteChip<F> {
18    type Record = ExecutionRecord;
19
20    type Program = Program;
21
22    fn name(&self) -> String {
23        "Byte".to_string()
24    }
25
26    fn preprocessed_width(&self) -> usize {
27        NUM_BYTE_PREPROCESSED_COLS
28    }
29
30    fn generate_preprocessed_trace(&self, _program: &Self::Program) -> Option<RowMajorMatrix<F>> {
31        let trace = Self::trace();
32        Some(trace)
33    }
34
35    fn generate_dependencies(&self, _input: &ExecutionRecord, _output: &mut ExecutionRecord) {
36        // Do nothing since this chip has no dependencies.
37    }
38
39    fn generate_trace(
40        &self,
41        input: &ExecutionRecord,
42        _output: &mut ExecutionRecord,
43    ) -> RowMajorMatrix<F> {
44        let mut trace =
45            RowMajorMatrix::new(zeroed_f_vec(NUM_BYTE_MULT_COLS * NUM_ROWS), NUM_BYTE_MULT_COLS);
46
47        for (lookup, mult) in input.byte_lookups.iter() {
48            let row = if lookup.opcode != ByteOpcode::U16Range {
49                (((lookup.b as u16) << 8) + lookup.c as u16) as usize
50            } else {
51                lookup.a1 as usize
52            };
53            let index = lookup.opcode as usize;
54
55            let cols: &mut ByteMultCols<F> = trace.row_mut(row).borrow_mut();
56            cols.multiplicities[index] += F::from_canonical_usize(*mult);
57        }
58
59        trace
60    }
61
62    fn included(&self, _shard: &Self::Record) -> bool {
63        true
64    }
65}