1use derive_more::derive::From;
2use openvm_bigint_transpiler::{
3 Rv32BaseAlu256Opcode, Rv32BranchEqual256Opcode, Rv32BranchLessThan256Opcode,
4 Rv32LessThan256Opcode, Rv32Mul256Opcode, Rv32Shift256Opcode,
5};
6use openvm_circuit::{
7 arch::{
8 SystemConfig, SystemPort, VmExtension, VmInventory, VmInventoryBuilder, VmInventoryError,
9 },
10 system::phantom::PhantomChip,
11};
12use openvm_circuit_derive::{AnyEnum, InstructionExecutor, VmConfig};
13use openvm_circuit_primitives::{
14 bitwise_op_lookup::{BitwiseOperationLookupBus, SharedBitwiseOperationLookupChip},
15 range_tuple::{RangeTupleCheckerBus, SharedRangeTupleCheckerChip},
16};
17use openvm_circuit_primitives_derive::{Chip, ChipUsageGetter};
18use openvm_instructions::{program::DEFAULT_PC_STEP, LocalOpcode};
19use openvm_rv32im_circuit::{
20 Rv32I, Rv32IExecutor, Rv32IPeriphery, Rv32Io, Rv32IoExecutor, Rv32IoPeriphery, Rv32M,
21 Rv32MExecutor, Rv32MPeriphery,
22};
23use openvm_stark_backend::p3_field::PrimeField32;
24use serde::{Deserialize, Serialize};
25
26use crate::*;
27
28#[derive(Clone, Debug, VmConfig, derive_new::new, Serialize, Deserialize)]
29pub struct Int256Rv32Config {
30 #[system]
31 pub system: SystemConfig,
32 #[extension]
33 pub rv32i: Rv32I,
34 #[extension]
35 pub rv32m: Rv32M,
36 #[extension]
37 pub io: Rv32Io,
38 #[extension]
39 pub bigint: Int256,
40}
41
42impl Default for Int256Rv32Config {
43 fn default() -> Self {
44 Self {
45 system: SystemConfig::default().with_continuations(),
46 rv32i: Rv32I,
47 rv32m: Rv32M::default(),
48 io: Rv32Io,
49 bigint: Int256::default(),
50 }
51 }
52}
53
54#[derive(Clone, Copy, Debug, Serialize, Deserialize)]
55pub struct Int256 {
56 #[serde(default = "default_range_tuple_checker_sizes")]
57 pub range_tuple_checker_sizes: [u32; 2],
58}
59
60impl Default for Int256 {
61 fn default() -> Self {
62 Self {
63 range_tuple_checker_sizes: default_range_tuple_checker_sizes(),
64 }
65 }
66}
67
68fn default_range_tuple_checker_sizes() -> [u32; 2] {
69 [1 << 8, 32 * (1 << 8)]
70}
71
72#[derive(ChipUsageGetter, Chip, InstructionExecutor, From, AnyEnum)]
73pub enum Int256Executor<F: PrimeField32> {
74 BaseAlu256(Rv32BaseAlu256Chip<F>),
75 LessThan256(Rv32LessThan256Chip<F>),
76 BranchEqual256(Rv32BranchEqual256Chip<F>),
77 BranchLessThan256(Rv32BranchLessThan256Chip<F>),
78 Multiplication256(Rv32Multiplication256Chip<F>),
79 Shift256(Rv32Shift256Chip<F>),
80}
81
82#[derive(From, ChipUsageGetter, Chip, AnyEnum)]
83pub enum Int256Periphery<F: PrimeField32> {
84 BitwiseOperationLookup(SharedBitwiseOperationLookupChip<8>),
85 RangeTupleChecker(SharedRangeTupleCheckerChip<2>),
87 Phantom(PhantomChip<F>),
88}
89
90impl<F: PrimeField32> VmExtension<F> for Int256 {
91 type Executor = Int256Executor<F>;
92 type Periphery = Int256Periphery<F>;
93
94 fn build(
95 &self,
96 builder: &mut VmInventoryBuilder<F>,
97 ) -> Result<VmInventory<Self::Executor, Self::Periphery>, VmInventoryError> {
98 let mut inventory = VmInventory::new();
99 let SystemPort {
100 execution_bus,
101 program_bus,
102 memory_bridge,
103 } = builder.system_port();
104 let range_checker_chip = builder.system_base().range_checker_chip.clone();
105 let bitwise_lu_chip = if let Some(&chip) = builder
106 .find_chip::<SharedBitwiseOperationLookupChip<8>>()
107 .first()
108 {
109 chip.clone()
110 } else {
111 let bitwise_lu_bus = BitwiseOperationLookupBus::new(builder.new_bus_idx());
112 let chip = SharedBitwiseOperationLookupChip::new(bitwise_lu_bus);
113 inventory.add_periphery_chip(chip.clone());
114 chip
115 };
116 let offline_memory = builder.system_base().offline_memory();
117 let address_bits = builder.system_config().memory_config.pointer_max_bits;
118
119 let range_tuple_chip = if let Some(chip) = builder
120 .find_chip::<SharedRangeTupleCheckerChip<2>>()
121 .into_iter()
122 .find(|c| {
123 c.bus().sizes[0] >= self.range_tuple_checker_sizes[0]
124 && c.bus().sizes[1] >= self.range_tuple_checker_sizes[1]
125 }) {
126 chip.clone()
127 } else {
128 let range_tuple_bus =
129 RangeTupleCheckerBus::new(builder.new_bus_idx(), self.range_tuple_checker_sizes);
130 let chip = SharedRangeTupleCheckerChip::new(range_tuple_bus);
131 inventory.add_periphery_chip(chip.clone());
132 chip
133 };
134
135 let base_alu_chip = Rv32BaseAlu256Chip::new(
136 Rv32HeapAdapterChip::new(
137 execution_bus,
138 program_bus,
139 memory_bridge,
140 address_bits,
141 bitwise_lu_chip.clone(),
142 ),
143 BaseAluCoreChip::new(bitwise_lu_chip.clone(), Rv32BaseAlu256Opcode::CLASS_OFFSET),
144 offline_memory.clone(),
145 );
146 inventory.add_executor(
147 base_alu_chip,
148 Rv32BaseAlu256Opcode::iter().map(|x| x.global_opcode()),
149 )?;
150
151 let less_than_chip = Rv32LessThan256Chip::new(
152 Rv32HeapAdapterChip::new(
153 execution_bus,
154 program_bus,
155 memory_bridge,
156 address_bits,
157 bitwise_lu_chip.clone(),
158 ),
159 LessThanCoreChip::new(bitwise_lu_chip.clone(), Rv32LessThan256Opcode::CLASS_OFFSET),
160 offline_memory.clone(),
161 );
162 inventory.add_executor(
163 less_than_chip,
164 Rv32LessThan256Opcode::iter().map(|x| x.global_opcode()),
165 )?;
166
167 let branch_equal_chip = Rv32BranchEqual256Chip::new(
168 Rv32HeapBranchAdapterChip::new(
169 execution_bus,
170 program_bus,
171 memory_bridge,
172 address_bits,
173 bitwise_lu_chip.clone(),
174 ),
175 BranchEqualCoreChip::new(Rv32BranchEqual256Opcode::CLASS_OFFSET, DEFAULT_PC_STEP),
176 offline_memory.clone(),
177 );
178 inventory.add_executor(
179 branch_equal_chip,
180 Rv32BranchEqual256Opcode::iter().map(|x| x.global_opcode()),
181 )?;
182
183 let branch_less_than_chip = Rv32BranchLessThan256Chip::new(
184 Rv32HeapBranchAdapterChip::new(
185 execution_bus,
186 program_bus,
187 memory_bridge,
188 address_bits,
189 bitwise_lu_chip.clone(),
190 ),
191 BranchLessThanCoreChip::new(
192 bitwise_lu_chip.clone(),
193 Rv32BranchLessThan256Opcode::CLASS_OFFSET,
194 ),
195 offline_memory.clone(),
196 );
197 inventory.add_executor(
198 branch_less_than_chip,
199 Rv32BranchLessThan256Opcode::iter().map(|x| x.global_opcode()),
200 )?;
201
202 let multiplication_chip = Rv32Multiplication256Chip::new(
203 Rv32HeapAdapterChip::new(
204 execution_bus,
205 program_bus,
206 memory_bridge,
207 address_bits,
208 bitwise_lu_chip.clone(),
209 ),
210 MultiplicationCoreChip::new(range_tuple_chip, Rv32Mul256Opcode::CLASS_OFFSET),
211 offline_memory.clone(),
212 );
213 inventory.add_executor(
214 multiplication_chip,
215 Rv32Mul256Opcode::iter().map(|x| x.global_opcode()),
216 )?;
217
218 let shift_chip = Rv32Shift256Chip::new(
219 Rv32HeapAdapterChip::new(
220 execution_bus,
221 program_bus,
222 memory_bridge,
223 address_bits,
224 bitwise_lu_chip.clone(),
225 ),
226 ShiftCoreChip::new(
227 bitwise_lu_chip.clone(),
228 range_checker_chip,
229 Rv32Shift256Opcode::CLASS_OFFSET,
230 ),
231 offline_memory.clone(),
232 );
233 inventory.add_executor(
234 shift_chip,
235 Rv32Shift256Opcode::iter().map(|x| x.global_opcode()),
236 )?;
237
238 Ok(inventory)
239 }
240}