openvm_algebra_circuit/modular_chip/
addsub.rs
1use std::{
2 cell::RefCell,
3 rc::Rc,
4 sync::{Arc, Mutex},
5};
6
7use openvm_algebra_transpiler::Rv32ModularArithmeticOpcode;
8use openvm_circuit::{arch::VmChipWrapper, system::memory::OfflineMemory};
9use openvm_circuit_derive::InstructionExecutor;
10use openvm_circuit_primitives::var_range::{
11 SharedVariableRangeCheckerChip, VariableRangeCheckerBus,
12};
13use openvm_circuit_primitives_derive::{Chip, ChipUsageGetter};
14use openvm_mod_circuit_builder::{
15 ExprBuilder, ExprBuilderConfig, FieldExpr, FieldExpressionCoreChip, FieldVariable,
16};
17use openvm_rv32_adapters::Rv32VecHeapAdapterChip;
18use openvm_stark_backend::p3_field::PrimeField32;
19
20pub fn addsub_expr(
21 config: ExprBuilderConfig,
22 range_bus: VariableRangeCheckerBus,
23) -> (FieldExpr, usize, usize) {
24 config.check_valid();
25 let builder = ExprBuilder::new(config, range_bus.range_max_bits);
26 let builder = Rc::new(RefCell::new(builder));
27
28 let x1 = ExprBuilder::new_input(builder.clone());
29 let x2 = ExprBuilder::new_input(builder.clone());
30 let x3 = x1.clone() + x2.clone();
31 let x4 = x1.clone() - x2.clone();
32 let is_add_flag = builder.borrow_mut().new_flag();
33 let is_sub_flag = builder.borrow_mut().new_flag();
34 let x5 = FieldVariable::select(is_sub_flag, &x4, &x1);
35 let mut x6 = FieldVariable::select(is_add_flag, &x3, &x5);
36 x6.save_output();
37 let builder = builder.borrow().clone();
38
39 (
40 FieldExpr::new(builder, range_bus, true),
41 is_add_flag,
42 is_sub_flag,
43 )
44}
45
46#[derive(Chip, ChipUsageGetter, InstructionExecutor)]
47pub struct ModularAddSubChip<F: PrimeField32, const BLOCKS: usize, const BLOCK_SIZE: usize>(
48 pub VmChipWrapper<
49 F,
50 Rv32VecHeapAdapterChip<F, 2, BLOCKS, BLOCKS, BLOCK_SIZE, BLOCK_SIZE>,
51 FieldExpressionCoreChip,
52 >,
53);
54
55impl<F: PrimeField32, const BLOCKS: usize, const BLOCK_SIZE: usize>
56 ModularAddSubChip<F, BLOCKS, BLOCK_SIZE>
57{
58 pub fn new(
59 adapter: Rv32VecHeapAdapterChip<F, 2, BLOCKS, BLOCKS, BLOCK_SIZE, BLOCK_SIZE>,
60 config: ExprBuilderConfig,
61 offset: usize,
62 range_checker: SharedVariableRangeCheckerChip,
63 offline_memory: Arc<Mutex<OfflineMemory<F>>>,
64 ) -> Self {
65 let (expr, is_add_flag, is_sub_flag) = addsub_expr(config, range_checker.bus());
66 let core = FieldExpressionCoreChip::new(
67 expr,
68 offset,
69 vec![
70 Rv32ModularArithmeticOpcode::ADD as usize,
71 Rv32ModularArithmeticOpcode::SUB as usize,
72 Rv32ModularArithmeticOpcode::SETUP_ADDSUB as usize,
73 ],
74 vec![is_add_flag, is_sub_flag],
75 range_checker,
76 "ModularAddSub",
77 false,
78 );
79 Self(VmChipWrapper::new(adapter, core, offline_memory))
80 }
81}