openvm_circuit/system/memory/offline_checker/
bus.rs
1use std::iter;
2
3use openvm_stark_backend::{
4 interaction::{BusIndex, InteractionBuilder, PermutationCheckBus},
5 p3_field::FieldAlgebra,
6};
7
8use crate::system::memory::MemoryAddress;
9
10#[derive(Clone, Copy, Debug, PartialEq, Eq)]
12pub struct MemoryBus {
13 pub inner: PermutationCheckBus,
14}
15
16impl MemoryBus {
17 pub const fn new(index: BusIndex) -> Self {
18 Self {
19 inner: PermutationCheckBus::new(index),
20 }
21 }
22}
23
24impl MemoryBus {
25 #[inline(always)]
26 pub fn index(&self) -> BusIndex {
27 self.inner.index
28 }
29
30 pub fn send<T: Clone>(
32 &self,
33 address: MemoryAddress<impl Into<T>, impl Into<T>>,
34 data: Vec<impl Into<T>>,
35 timestamp: impl Into<T>,
36 ) -> MemoryBusInteraction<T> {
37 self.push(true, address, data, timestamp)
38 }
39
40 pub fn receive<T: Clone>(
42 &self,
43 address: MemoryAddress<impl Into<T>, impl Into<T>>,
44 data: Vec<impl Into<T>>,
45 timestamp: impl Into<T>,
46 ) -> MemoryBusInteraction<T> {
47 self.push(false, address, data, timestamp)
48 }
49
50 fn push<T: Clone>(
52 &self,
53 is_send: bool,
54 address: MemoryAddress<impl Into<T>, impl Into<T>>,
55 data: Vec<impl Into<T>>,
56 timestamp: impl Into<T>,
57 ) -> MemoryBusInteraction<T> {
58 MemoryBusInteraction {
59 bus: self.inner,
60 is_send,
61 address: MemoryAddress::new(address.address_space.into(), address.pointer.into()),
62 data: data.into_iter().map(|item| item.into()).collect(),
63 timestamp: timestamp.into(),
64 }
65 }
66}
67
68#[derive(Clone, Debug)]
69pub struct MemoryBusInteraction<T> {
70 pub bus: PermutationCheckBus,
71 pub is_send: bool,
72 pub address: MemoryAddress<T, T>,
73 pub data: Vec<T>,
74 pub timestamp: T,
75}
76
77impl<T: FieldAlgebra> MemoryBusInteraction<T> {
78 pub fn eval<AB>(self, builder: &mut AB, direction: impl Into<AB::Expr>)
87 where
88 AB: InteractionBuilder<Expr = T>,
89 {
90 let fields = iter::empty()
91 .chain(iter::once(self.address.address_space))
92 .chain(iter::once(self.address.pointer))
93 .chain(self.data)
94 .chain(iter::once(self.timestamp));
95
96 if self.is_send {
97 self.bus.interact(builder, fields, direction);
98 } else {
99 self.bus
100 .interact(builder, fields, AB::Expr::NEG_ONE * direction.into());
101 }
102 }
103}