Skip to main content

sp1_hypercube/air/
machine.rs

1use std::mem::MaybeUninit;
2
3use crate::{septic_digest::SepticDigest, MachineRecord};
4use slop_air::BaseAir;
5use slop_algebra::Field;
6use slop_matrix::dense::RowMajorMatrix;
7pub use sp1_derive::MachineAir;
8
9#[macro_export]
10/// Macro to get the name of a chip.
11macro_rules! chip_name {
12    ($chip:ident, $field:ty) => {
13        <$chip as MachineAir<$field>>::name(&$chip {})
14    };
15}
16
17/// An AIR that is part of a multi table AIR arithmetization.
18pub trait MachineAir<F: Field>: BaseAir<F> + 'static + Send + Sync {
19    /// The execution record containing events for producing the air trace.
20    type Record: MachineRecord;
21
22    /// The program that defines the control flow of the machine.
23    type Program: MachineProgram<F>;
24
25    /// A unique identifier for this AIR as part of a machine.
26    fn name(&self) -> &'static str;
27
28    /// The number of rows in the trace, if the chip is included.
29    ///
30    /// **Warning**:: if the chip is not included, `num_rows` is allowed to return anything.
31    fn num_rows(&self, _input: &Self::Record) -> Option<usize> {
32        None
33    }
34
35    /// Generate the trace for a given execution record.
36    ///
37    /// - `input` is the execution record containing the events to be written to the trace.
38    /// - `output` is the execution record containing events that the `MachineAir` can add to the
39    ///   record such as byte lookup requests.
40    fn generate_trace(&self, input: &Self::Record, output: &mut Self::Record) -> RowMajorMatrix<F> {
41        let padded_nb_rows = self.num_rows(input).unwrap();
42        let num_columns = <Self as BaseAir<F>>::width(self);
43        let mut values: Vec<F> = Vec::with_capacity(padded_nb_rows * num_columns);
44        self.generate_trace_into(input, output, values.spare_capacity_mut());
45
46        unsafe {
47            values.set_len(padded_nb_rows * num_columns);
48        }
49
50        RowMajorMatrix::new(values, num_columns)
51    }
52
53    /// Generate the dependencies for a given execution record.
54    fn generate_dependencies(&self, input: &Self::Record, output: &mut Self::Record) {
55        self.generate_trace(input, output);
56    }
57
58    /// Generate the trace into a slice of `MaybeUninit<F>`.
59    fn generate_trace_into(
60        &self,
61        input: &Self::Record,
62        output: &mut Self::Record,
63        buffer: &mut [MaybeUninit<F>],
64    );
65
66    /// Whether this execution record contains events for this air.
67    fn included(&self, shard: &Self::Record) -> bool;
68
69    /// The width of the preprocessed trace.
70    fn preprocessed_width(&self) -> usize {
71        0
72    }
73
74    /// The number of rows in the preprocessed trace
75    fn preprocessed_num_rows(&self, _program: &Self::Program) -> Option<usize> {
76        None
77    }
78
79    /// The number of rows in the preprocessed trace using the program and the instr len.
80    fn preprocessed_num_rows_with_instrs_len(
81        &self,
82        _program: &Self::Program,
83        _instrs_len: usize,
84    ) -> Option<usize> {
85        None
86    }
87
88    /// Generate the preprocessed trace into a slice of `MaybeUninit<F>`.
89    fn generate_preprocessed_trace_into(&self, _: &Self::Program, _: &mut [MaybeUninit<F>]) {}
90
91    /// Generate the preprocessed trace given a specific program.
92    fn generate_preprocessed_trace(&self, program: &Self::Program) -> Option<RowMajorMatrix<F>> {
93        if self.preprocessed_width() == 0 {
94            return None;
95        }
96
97        let padded_nb_rows = self.preprocessed_num_rows(program).unwrap();
98        let num_columns = self.preprocessed_width();
99        let mut values: Vec<F> = Vec::with_capacity(padded_nb_rows * num_columns);
100        self.generate_preprocessed_trace_into(program, values.spare_capacity_mut());
101
102        unsafe {
103            values.set_len(padded_nb_rows * num_columns);
104        }
105
106        Some(RowMajorMatrix::new(values, num_columns))
107    }
108}
109
110/// A program that defines the control flow of a machine through a program counter.
111pub trait MachineProgram<F>: Send + Sync {
112    /// Gets the starting program counter.
113    fn pc_start(&self) -> [F; 3];
114    /// Gets the initial global cumulative sum.
115    fn initial_global_cumulative_sum(&self) -> SepticDigest<F>;
116    /// Gets the flag indicating if untrusted programs are allowed.
117    fn enable_untrusted_programs(&self) -> F;
118}