sp1_core_machine/operations/
trap.rs1use crate::air::MemoryAirBuilder;
2#[cfg(feature = "mprotect")]
3use slop_air::AirBuilder;
4use slop_algebra::{AbstractField, Field, PrimeField32};
5use sp1_core_executor::{
6 events::{ByteRecord, MemoryRecordEnum},
7 TrapResult,
8};
9use sp1_derive::AlignedBorrow;
10#[cfg(feature = "mprotect")]
11use sp1_hypercube::air::BaseAirBuilder;
12
13use sp1_hypercube::air::SP1AirBuilder;
14use sp1_hypercube::Word;
15use struct_reflection::{StructReflection, StructReflectionHelper};
16
17use crate::memory::MemoryAccessCols;
18
19#[derive(AlignedBorrow, Default, Debug, Clone, Copy, StructReflection)]
20#[repr(C)]
21pub struct TrapOperation<T> {
22 pub next_pc_reader: MemoryAccessCols<T>,
23 pub code_writer: MemoryAccessCols<T>,
24 pub pc_writer: MemoryAccessCols<T>,
25}
26
27impl<F: PrimeField32> TrapOperation<F> {
28 pub fn populate(&mut self, record: &mut impl ByteRecord, trap_result: TrapResult) {
29 self.next_pc_reader.populate(MemoryRecordEnum::Read(trap_result.handler_record), record);
30 self.code_writer.populate(MemoryRecordEnum::Write(trap_result.code_record), record);
31 self.pc_writer.populate(MemoryRecordEnum::Write(trap_result.pc_record), record);
32 }
33}
34
35impl<F: Field> TrapOperation<F> {
36 #[allow(clippy::too_many_arguments)]
37 pub fn eval<AB: SP1AirBuilder>(
38 builder: &mut AB,
39 cols: TrapOperation<AB::Var>,
40 clk_high: AB::Expr,
41 clk_low: AB::Expr,
42 code: AB::Expr,
43 pc: [AB::Expr; 3],
44 addresses: [[AB::Var; 3]; 3],
45 is_real: AB::Expr,
46 ) -> [AB::Var; 3] {
47 builder.assert_bool(is_real.clone());
48 #[cfg(feature = "mprotect")]
49 {
50 let public_values = builder.extract_public_values();
51 builder.when(is_real.clone()).assert_one(public_values.enable_trap_handler);
52
53 for i in 0..3 {
54 builder
55 .when(is_real.clone())
56 .assert_all_eq(public_values.trap_context[i], addresses[i]);
57 }
58 }
59 builder.eval_memory_access_read(
61 clk_high.clone(),
62 clk_low.clone(),
63 &addresses[0].map(Into::into),
64 cols.next_pc_reader,
65 is_real.clone(),
66 );
67
68 builder.eval_memory_access_write(
71 clk_high.clone(),
72 clk_low.clone(),
73 &addresses[1].map(Into::into),
74 cols.code_writer,
75 Word::extend_expr::<AB>(code.clone()),
76 is_real.clone(),
77 );
78
79 builder.eval_memory_access_write(
82 clk_high.clone(),
83 clk_low.clone(),
84 &addresses[2].map(Into::into),
85 cols.pc_writer,
86 Word([pc[0].clone(), pc[1].clone(), pc[2].clone(), AB::Expr::zero()]),
87 is_real.clone(),
88 );
89
90 [
91 cols.next_pc_reader.prev_value[0],
92 cols.next_pc_reader.prev_value[1],
93 cols.next_pc_reader.prev_value[2],
94 ]
95 }
96}