openvm_circuit/arch/testing/execution/
mod.rs

1use std::{borrow::BorrowMut, mem::size_of, sync::Arc};
2
3use air::DummyExecutionInteractionCols;
4use openvm_stark_backend::{
5    config::{StarkGenericConfig, Val},
6    p3_field::{Field, FieldAlgebra, PrimeField32},
7    p3_matrix::dense::RowMajorMatrix,
8    prover::{cpu::CpuBackend, types::AirProvingContext},
9    Chip, ChipUsageGetter,
10};
11
12use crate::arch::{ExecutionBus, ExecutionState};
13
14pub mod air;
15#[cfg(feature = "cuda")]
16mod cuda;
17#[cfg(feature = "cuda")]
18pub use cuda::*;
19
20#[derive(Debug)]
21pub struct ExecutionTester<F: Field> {
22    pub bus: ExecutionBus,
23    pub records: Vec<DummyExecutionInteractionCols<F>>,
24}
25
26impl<F: PrimeField32> ExecutionTester<F> {
27    pub fn new(bus: ExecutionBus) -> Self {
28        Self {
29            bus,
30            records: vec![],
31        }
32    }
33
34    pub fn execute(
35        &mut self,
36        initial_state: ExecutionState<u32>,
37        final_state: ExecutionState<u32>,
38    ) {
39        self.records.push(DummyExecutionInteractionCols {
40            count: F::NEG_ONE, // send
41            initial_state: initial_state.map(F::from_canonical_u32),
42            final_state: final_state.map(F::from_canonical_u32),
43        })
44    }
45
46    pub fn last_from_pc(&self) -> F {
47        self.records.last().unwrap().initial_state.pc
48    }
49
50    pub fn last_to_pc(&self) -> F {
51        self.records.last().unwrap().final_state.pc
52    }
53}
54
55impl<SC: StarkGenericConfig, RA> Chip<RA, CpuBackend<SC>> for ExecutionTester<Val<SC>>
56where
57    Val<SC>: Field,
58{
59    fn generate_proving_ctx(&self, _: RA) -> AirProvingContext<CpuBackend<SC>> {
60        let height = self.records.len().next_power_of_two();
61        let width = self.trace_width();
62        let mut values = Val::<SC>::zero_vec(height * width);
63        // This zip only goes through records. The padding rows between records.len()..height
64        // are filled with zeros - in particular count = 0 so nothing is added to bus.
65        for (row, record) in values.chunks_mut(width).zip(&self.records) {
66            *row.borrow_mut() = *record;
67        }
68        AirProvingContext::simple_no_pis(Arc::new(RowMajorMatrix::new(values, width)))
69    }
70}
71impl<F: Field> ChipUsageGetter for ExecutionTester<F> {
72    fn air_name(&self) -> String {
73        "ExecutionDummyAir".to_string()
74    }
75    fn current_trace_height(&self) -> usize {
76        self.records.len()
77    }
78
79    fn trace_width(&self) -> usize {
80        size_of::<DummyExecutionInteractionCols<u8>>()
81    }
82}