Skip to main content

sp1_hypercube/air/
machine.rs

1use std::mem::MaybeUninit;
2
3use crate::{septic_digest::SepticDigest, MachineRecord, UntrustedConfig};
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    /// A list of column names. The length should equal `self.width()`.
29    fn column_names(&self) -> Vec<String> {
30        // Default implementation returns generic column names.
31        (0..self.width()).map(|i| format!("col_{i}")).collect()
32    }
33
34    /// The number of rows in the trace, if the chip is included.
35    ///
36    /// **Warning**:: if the chip is not included, `num_rows` is allowed to return anything.
37    fn num_rows(&self, _input: &Self::Record) -> Option<usize> {
38        None
39    }
40
41    /// Generate the trace for a given execution record.
42    ///
43    /// - `input` is the execution record containing the events to be written to the trace.
44    /// - `output` is the execution record containing events that the `MachineAir` can add to the
45    ///   record such as byte lookup requests.
46    fn generate_trace(&self, input: &Self::Record, output: &mut Self::Record) -> RowMajorMatrix<F> {
47        let padded_nb_rows = self.num_rows(input).unwrap();
48        let num_columns = <Self as BaseAir<F>>::width(self);
49        let mut values: Vec<F> = Vec::with_capacity(padded_nb_rows * num_columns);
50        self.generate_trace_into(input, output, values.spare_capacity_mut());
51
52        unsafe {
53            values.set_len(padded_nb_rows * num_columns);
54        }
55
56        RowMajorMatrix::new(values, num_columns)
57    }
58
59    /// Generate the dependencies for a given execution record.
60    fn generate_dependencies(&self, input: &Self::Record, output: &mut Self::Record) {
61        self.generate_trace(input, output);
62    }
63
64    /// Generate the trace into a slice of `MaybeUninit<F>`.
65    fn generate_trace_into(
66        &self,
67        input: &Self::Record,
68        output: &mut Self::Record,
69        buffer: &mut [MaybeUninit<F>],
70    );
71
72    /// Whether this execution record contains events for this air.
73    fn included(&self, shard: &Self::Record) -> bool;
74
75    /// The width of the preprocessed trace.
76    fn preprocessed_width(&self) -> usize {
77        0
78    }
79
80    /// The number of rows in the preprocessed trace
81    fn preprocessed_num_rows(&self, _program: &Self::Program) -> Option<usize> {
82        None
83    }
84
85    /// The number of rows in the preprocessed trace using the program and the instr len.
86    fn preprocessed_num_rows_with_instrs_len(
87        &self,
88        _program: &Self::Program,
89        _instrs_len: usize,
90    ) -> Option<usize> {
91        None
92    }
93
94    /// Generate the preprocessed trace into a slice of `MaybeUninit<F>`.
95    fn generate_preprocessed_trace_into(&self, _: &Self::Program, _: &mut [MaybeUninit<F>]) {}
96
97    /// Generate the preprocessed trace given a specific program.
98    fn generate_preprocessed_trace(&self, program: &Self::Program) -> Option<RowMajorMatrix<F>> {
99        if self.preprocessed_width() == 0 {
100            return None;
101        }
102
103        let padded_nb_rows = self.preprocessed_num_rows(program).unwrap();
104        let num_columns = self.preprocessed_width();
105        let mut values: Vec<F> = Vec::with_capacity(padded_nb_rows * num_columns);
106        self.generate_preprocessed_trace_into(program, values.spare_capacity_mut());
107
108        unsafe {
109            values.set_len(padded_nb_rows * num_columns);
110        }
111
112        Some(RowMajorMatrix::new(values, num_columns))
113    }
114}
115
116/// A program that defines the control flow of a machine through a program counter.
117pub trait MachineProgram<F>: Send + Sync {
118    /// Gets the starting program counter.
119    fn pc_start(&self) -> [F; 3];
120    /// Gets the initial global cumulative sum.
121    fn initial_global_cumulative_sum(&self) -> SepticDigest<F>;
122    /// Gets the metadata on configuration regarding untrusted programs.
123    fn untrusted_config(&self) -> UntrustedConfig<F>;
124}