1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
use p3_air::AirBuilder;
use p3_field::Field;
use sp1_core::air::BaseAirBuilder;

use crate::{
    air::{RecursionPublicValues, SP1RecursionAirBuilder},
    cpu::{CpuChip, CpuCols},
};

impl<F: Field, const L: usize> CpuChip<F, L> {
    /// Eval the system instructions (TRAP, HALT).
    pub fn eval_system_instructions<AB>(
        &self,
        builder: &mut AB,
        local: &CpuCols<AB::Var>,
        next: &CpuCols<AB::Var>,
        public_values: &RecursionPublicValues<AB::Expr>,
    ) where
        AB: SP1RecursionAirBuilder<F = F>,
    {
        let is_system_instruction = self.is_system_instruction::<AB>(local);

        // Verify that the last real row is either TRAP or HALT.
        builder
            .when_transition()
            .when(local.is_real)
            .when_not(next.is_real)
            .assert_one(is_system_instruction.clone());

        builder
            .when_last_row()
            .when(local.is_real)
            .assert_one(is_system_instruction.clone());

        // Verify that all other real rows are not TRAP or HALT.
        builder
            .when_transition()
            .when(local.is_real)
            .when(next.is_real)
            .assert_zero(is_system_instruction);

        // Verify the correct public value exit code.
        builder
            .when(local.selectors.is_trap)
            .assert_one(public_values.exit_code.clone());

        builder
            .when(local.selectors.is_halt)
            .assert_zero(public_values.exit_code.clone());
    }
}