openvm-circuit 2.0.1

OpenVM circuits
Documentation
use openvm_instructions::{instruction::Instruction, SystemOpcode, VmOpcode};
use openvm_stark_backend::p3_field::{PrimeCharacteristicRing, PrimeField32};
use openvm_stark_sdk::p3_baby_bear::BabyBear;

use super::PhantomExecutor;
use crate::{
    arch::{
        instructions::LocalOpcode,
        testing::{TestBuilder, TestChipHarness, VmChipTestBuilder},
        Arena, ExecutionState, PreflightExecutor,
    },
    system::phantom::{PhantomAir, PhantomChip, PhantomFiller},
};

type F = BabyBear;

fn run_phantom_test<E, RA>(
    tester: &mut impl TestBuilder<F>,
    executor: &mut E,
    arena: &mut RA,
    phantom_opcode: VmOpcode,
    num_nops: usize,
) where
    E: PreflightExecutor<F, RA>,
    RA: Arena,
{
    let nop = Instruction::from_isize(phantom_opcode, 0, 0, 0, 0, 0);
    let mut state: ExecutionState<F> = ExecutionState::new(F::ZERO, F::ONE);

    for _ in 0..num_nops {
        tester.execute_with_pc(executor, arena, &nop, state.pc.as_canonical_u32());
        let new_state = tester.execution_final_state();
        assert_eq!(state.pc + F::from_usize(4), new_state.pc);
        assert_eq!(state.timestamp + F::ONE, new_state.timestamp);
        state = new_state;
    }
}

#[test]
fn test_nops_and_terminate() {
    const NUM_NOPS: usize = 100;
    let phantom_opcode = SystemOpcode::PHANTOM.global_opcode();

    let mut tester = VmChipTestBuilder::default();
    let executor = PhantomExecutor::<F>::new(Default::default(), phantom_opcode);
    let chip = PhantomChip::new(PhantomFiller, tester.memory_helper());
    let air = PhantomAir {
        execution_bridge: tester.execution_bridge(),
        phantom_opcode,
    };
    let mut harness = TestChipHarness::with_capacity(executor, air, chip, NUM_NOPS);

    run_phantom_test(
        &mut tester,
        &mut harness.executor,
        &mut harness.arena,
        phantom_opcode,
        NUM_NOPS,
    );

    let tester = tester.build().load(harness).finalize();
    tester.simple_test().expect("Verification failed");
}

#[cfg(feature = "cuda")]
#[test]
fn test_cuda_phantom_tracegen() {
    use crate::{
        arch::{
            testing::{GpuChipTestBuilder, GpuTestChipHarness},
            EmptyMultiRowLayout,
        },
        system::{cuda::phantom::PhantomChipGPU, phantom::PhantomRecord},
    };

    const NUM_NOPS: usize = 100;
    let phantom_opcode = SystemOpcode::PHANTOM.global_opcode();
    let mut tester = GpuChipTestBuilder::default();

    let executor = PhantomExecutor::<F>::new(Default::default(), phantom_opcode);
    let air = PhantomAir {
        execution_bridge: tester.execution_bridge(),
        phantom_opcode,
    };
    let gpu_chip = PhantomChipGPU::new(tester.range_checker().device_ctx.clone());
    let cpu_chip = PhantomChip::new(PhantomFiller, tester.dummy_memory_helper());
    let mut harness =
        GpuTestChipHarness::with_capacity(executor, air, gpu_chip, cpu_chip, NUM_NOPS);

    run_phantom_test(
        &mut tester,
        &mut harness.executor,
        &mut harness.dense_arena,
        phantom_opcode,
        NUM_NOPS,
    );

    harness
        .dense_arena
        .get_record_seeker::<&mut PhantomRecord, EmptyMultiRowLayout>()
        .transfer_to_matrix_arena(&mut harness.matrix_arena);

    tester
        .build()
        .load_gpu_harness(harness)
        .simple_test()
        .expect("Verification failed");
}