openvm_rv32im_circuit/adapters/
mod.rs

1use std::ops::Mul;
2
3use openvm_circuit::system::memory::{MemoryController, RecordId};
4use openvm_stark_backend::p3_field::{FieldAlgebra, PrimeField32};
5
6mod alu;
7mod branch;
8mod jalr;
9mod loadstore;
10mod mul;
11mod rdwrite;
12
13pub use alu::*;
14pub use branch::*;
15pub use jalr::*;
16pub use loadstore::*;
17pub use mul::*;
18pub use openvm_instructions::riscv::{RV32_CELL_BITS, RV32_REGISTER_NUM_LIMBS};
19pub use rdwrite::*;
20
21/// 256-bit heap integer stored as 32 bytes (32 limbs of 8-bits)
22pub const INT256_NUM_LIMBS: usize = 32;
23
24// For soundness, should be <= 16
25pub const RV_IS_TYPE_IMM_BITS: usize = 12;
26
27// Branch immediate value is in [-2^12, 2^12)
28pub const RV_B_TYPE_IMM_BITS: usize = 13;
29
30pub const RV_J_TYPE_IMM_BITS: usize = 21;
31
32/// Convert the RISC-V register data (32 bits represented as 4 bytes, where each byte is represented as a field element)
33/// back into its value as u32.
34pub fn compose<F: PrimeField32>(ptr_data: [F; RV32_REGISTER_NUM_LIMBS]) -> u32 {
35    let mut val = 0;
36    for (i, limb) in ptr_data.map(|x| x.as_canonical_u32()).iter().enumerate() {
37        val += limb << (i * 8);
38    }
39    val
40}
41
42/// inverse of `compose`
43pub fn decompose<F: PrimeField32>(value: u32) -> [F; RV32_REGISTER_NUM_LIMBS] {
44    std::array::from_fn(|i| {
45        F::from_canonical_u32((value >> (RV32_CELL_BITS * i)) & ((1 << RV32_CELL_BITS) - 1))
46    })
47}
48
49/// Read register value as [RV32_REGISTER_NUM_LIMBS] limbs from memory.
50/// Returns the read record and the register value as u32.
51/// Does not make any range check calls.
52pub fn read_rv32_register<F: PrimeField32>(
53    memory: &mut MemoryController<F>,
54    address_space: F,
55    pointer: F,
56) -> (RecordId, u32) {
57    debug_assert_eq!(address_space, F::ONE);
58    let record = memory.read::<RV32_REGISTER_NUM_LIMBS>(address_space, pointer);
59    let val = compose(record.1);
60    (record.0, val)
61}
62
63/// Peeks at the value of a register without updating the memory state or incrementing the timestamp.
64pub fn unsafe_read_rv32_register<F: PrimeField32>(memory: &MemoryController<F>, pointer: F) -> u32 {
65    let data = memory.unsafe_read::<RV32_REGISTER_NUM_LIMBS>(F::ONE, pointer);
66    compose(data)
67}
68
69pub fn abstract_compose<T: FieldAlgebra, V: Mul<T, Output = T>>(
70    data: [V; RV32_REGISTER_NUM_LIMBS],
71) -> T {
72    data.into_iter()
73        .enumerate()
74        .fold(T::ZERO, |acc, (i, limb)| {
75            acc + limb * T::from_canonical_u32(1 << (i * RV32_CELL_BITS))
76        })
77}