use std::{borrow::BorrowMut, mem::size_of};
use air::DummyExecutionInteractionCols;
use openvm_circuit_primitives::Chip;
use openvm_cpu_backend::CpuBackend;
use openvm_stark_backend::{
p3_field::{Field, PrimeCharacteristicRing, PrimeField32},
p3_matrix::dense::RowMajorMatrix,
prover::AirProvingContext,
StarkProtocolConfig, Val,
};
use crate::arch::{ExecutionBus, ExecutionState};
pub mod air;
#[cfg(feature = "cuda")]
mod cuda;
#[cfg(feature = "cuda")]
pub use cuda::*;
#[derive(Debug)]
pub struct ExecutionTester<F: Field> {
pub bus: ExecutionBus,
pub records: Vec<DummyExecutionInteractionCols<F>>,
}
impl<F: PrimeField32> ExecutionTester<F> {
pub fn new(bus: ExecutionBus) -> Self {
Self {
bus,
records: vec![],
}
}
pub fn execute(
&mut self,
initial_state: ExecutionState<u32>,
final_state: ExecutionState<u32>,
) {
self.records.push(DummyExecutionInteractionCols {
count: F::NEG_ONE, initial_state: initial_state.map(F::from_u32),
final_state: final_state.map(F::from_u32),
})
}
pub fn last_from_pc(&self) -> F {
self.records.last().unwrap().initial_state.pc
}
pub fn last_to_pc(&self) -> F {
self.records.last().unwrap().final_state.pc
}
}
impl<SC: StarkProtocolConfig, RA> Chip<RA, CpuBackend<SC>> for ExecutionTester<Val<SC>>
where
Val<SC>: Field,
{
fn generate_proving_ctx(&self, _: RA) -> AirProvingContext<CpuBackend<SC>> {
let height = self.records.len().next_power_of_two();
let width = size_of::<DummyExecutionInteractionCols<u8>>();
let mut values = Val::<SC>::zero_vec(height * width);
for (row, record) in values.chunks_mut(width).zip(&self.records) {
*row.borrow_mut() = *record;
}
AirProvingContext::simple_no_pis(RowMajorMatrix::new(values, width))
}
}