openvm_circuit/system/memory/adapter/
air.rs
1use std::{borrow::Borrow, mem::size_of};
2
3use openvm_circuit_primitives::{
4 is_less_than::{IsLessThanIo, IsLtSubAir},
5 SubAir,
6};
7use openvm_stark_backend::{
8 interaction::InteractionBuilder,
9 p3_air::{Air, AirBuilder, BaseAir},
10 p3_field::FieldAlgebra,
11 p3_matrix::Matrix,
12 rap::{BaseAirWithPublicValues, PartitionedBaseAir},
13};
14
15use crate::system::memory::{
16 adapter::columns::AccessAdapterCols, offline_checker::MemoryBus, MemoryAddress,
17};
18
19#[derive(Clone, Debug)]
20pub struct AccessAdapterAir<const N: usize> {
21 pub memory_bus: MemoryBus,
22 pub lt_air: IsLtSubAir,
23}
24
25impl<T, const N: usize> BaseAirWithPublicValues<T> for AccessAdapterAir<N> {}
26impl<T, const N: usize> PartitionedBaseAir<T> for AccessAdapterAir<N> {}
27impl<T, const N: usize> BaseAir<T> for AccessAdapterAir<N> {
28 fn width(&self) -> usize {
29 size_of::<AccessAdapterCols<u8, N>>()
30 }
31}
32
33impl<const N: usize, AB: InteractionBuilder> Air<AB> for AccessAdapterAir<N> {
34 fn eval(&self, builder: &mut AB) {
35 let main = builder.main();
36
37 let local = main.row_slice(0);
38 let local: &AccessAdapterCols<AB::Var, N> = (*local).borrow();
39
40 builder.assert_bool(local.is_split);
41 builder.assert_bool(local.is_valid);
42 builder.assert_bool(local.is_right_larger);
43
44 builder
49 .when(local.is_split)
50 .assert_eq(local.left_timestamp, local.right_timestamp);
51
52 self.lt_air.eval(
53 builder,
54 (
55 IsLessThanIo {
56 x: local.left_timestamp.into(),
57 y: local.right_timestamp.into(),
58 out: local.is_right_larger.into(),
59 count: local.is_valid.into(),
60 },
61 &local.lt_aux,
62 ),
63 );
64
65 let parent_timestamp = local.is_right_larger * local.right_timestamp
66 + (AB::Expr::ONE - local.is_right_larger) * local.left_timestamp;
67
68 let direction = local.is_valid * (AB::Expr::TWO * local.is_split - AB::Expr::ONE);
73
74 self.memory_bus
75 .receive(local.address, local.values.to_vec(), parent_timestamp)
76 .eval(builder, direction.clone());
77
78 self.memory_bus
79 .send(
80 local.address,
81 local.values[..N / 2].to_vec(),
82 local.left_timestamp,
83 )
84 .eval(builder, direction.clone());
85
86 self.memory_bus
87 .send(
88 MemoryAddress::new(
89 local.address.address_space,
90 local.address.pointer + AB::Expr::from_canonical_usize(N / 2),
91 ),
92 local.values[N / 2..].to_vec(),
93 local.right_timestamp,
94 )
95 .eval(builder, direction.clone());
96 }
97}