sp1_recursion_core_v2/runtime/
instruction.rs

1use std::borrow::Borrow;
2
3use p3_field::{AbstractExtensionField, AbstractField};
4use serde::{Deserialize, Serialize};
5
6use crate::*;
7
8#[derive(Debug, Clone, Serialize, Deserialize)]
9pub enum Instruction<F> {
10    BaseAlu(BaseAluInstr<F>),
11    ExtAlu(ExtAluInstr<F>),
12    Mem(MemInstr<F>),
13    Poseidon2(Box<Poseidon2Instr<F>>),
14    ExpReverseBitsLen(ExpReverseBitsInstr<F>),
15    HintBits(HintBitsInstr<F>),
16    FriFold(Box<FriFoldInstr<F>>),
17    Print(PrintInstr<F>),
18    HintExt2Felts(HintExt2FeltsInstr<F>),
19    CommitPublicValues(Box<CommitPublicValuesInstr<F>>),
20    Hint(HintInstr<F>),
21}
22
23#[derive(Clone, Debug, Serialize, Deserialize)]
24pub struct HintBitsInstr<F> {
25    /// Addresses and mults of the output bits.
26    pub output_addrs_mults: Vec<(Address<F>, F)>,
27    /// Input value to decompose.
28    pub input_addr: Address<F>,
29}
30
31#[derive(Clone, Debug, Serialize, Deserialize)]
32pub struct PrintInstr<F> {
33    pub field_elt_type: FieldEltType,
34    pub addr: Address<F>,
35}
36
37#[derive(Clone, Debug, Serialize, Deserialize)]
38pub struct HintInstr<F> {
39    /// Addresses and mults of the output felts.
40    pub output_addrs_mults: Vec<(Address<F>, F)>,
41}
42
43#[derive(Clone, Debug, Serialize, Deserialize)]
44pub struct HintExt2FeltsInstr<F> {
45    /// Addresses and mults of the output bits.
46    pub output_addrs_mults: [(Address<F>, F); D],
47    /// Input value to decompose.
48    pub input_addr: Address<F>,
49}
50
51#[derive(Clone, Debug, Serialize, Deserialize)]
52pub enum FieldEltType {
53    Base,
54    Extension,
55}
56
57pub fn base_alu<F: AbstractField>(
58    opcode: BaseAluOpcode,
59    mult: u32,
60    out: u32,
61    in1: u32,
62    in2: u32,
63) -> Instruction<F> {
64    Instruction::BaseAlu(BaseAluInstr {
65        opcode,
66        mult: F::from_canonical_u32(mult),
67        addrs: BaseAluIo {
68            out: Address(F::from_canonical_u32(out)),
69            in1: Address(F::from_canonical_u32(in1)),
70            in2: Address(F::from_canonical_u32(in2)),
71        },
72    })
73}
74
75pub fn ext_alu<F: AbstractField>(
76    opcode: ExtAluOpcode,
77    mult: u32,
78    out: u32,
79    in1: u32,
80    in2: u32,
81) -> Instruction<F> {
82    Instruction::ExtAlu(ExtAluInstr {
83        opcode,
84        mult: F::from_canonical_u32(mult),
85        addrs: ExtAluIo {
86            out: Address(F::from_canonical_u32(out)),
87            in1: Address(F::from_canonical_u32(in1)),
88            in2: Address(F::from_canonical_u32(in2)),
89        },
90    })
91}
92
93pub fn mem<F: AbstractField>(
94    kind: MemAccessKind,
95    mult: u32,
96    addr: u32,
97    val: u32,
98) -> Instruction<F> {
99    mem_single(kind, mult, addr, F::from_canonical_u32(val))
100}
101
102pub fn mem_single<F: AbstractField>(
103    kind: MemAccessKind,
104    mult: u32,
105    addr: u32,
106    val: F,
107) -> Instruction<F> {
108    mem_block(kind, mult, addr, Block::from(val))
109}
110
111pub fn mem_ext<F: AbstractField + Copy, EF: AbstractExtensionField<F>>(
112    kind: MemAccessKind,
113    mult: u32,
114    addr: u32,
115    val: EF,
116) -> Instruction<F> {
117    mem_block(kind, mult, addr, val.as_base_slice().into())
118}
119
120pub fn mem_block<F: AbstractField>(
121    kind: MemAccessKind,
122    mult: u32,
123    addr: u32,
124    val: Block<F>,
125) -> Instruction<F> {
126    Instruction::Mem(MemInstr {
127        addrs: MemIo { inner: Address(F::from_canonical_u32(addr)) },
128        vals: MemIo { inner: val },
129        mult: F::from_canonical_u32(mult),
130        kind,
131    })
132}
133
134pub fn poseidon2<F: AbstractField>(
135    mults: [u32; WIDTH],
136    output: [u32; WIDTH],
137    input: [u32; WIDTH],
138) -> Instruction<F> {
139    Instruction::Poseidon2(Box::new(Poseidon2Instr {
140        mults: mults.map(F::from_canonical_u32),
141        addrs: Poseidon2Io {
142            output: output.map(F::from_canonical_u32).map(Address),
143            input: input.map(F::from_canonical_u32).map(Address),
144        },
145    }))
146}
147
148pub fn exp_reverse_bits_len<F: AbstractField>(
149    mult: u32,
150    base: F,
151    exp: Vec<F>,
152    result: F,
153) -> Instruction<F> {
154    Instruction::ExpReverseBitsLen(ExpReverseBitsInstr {
155        mult: F::from_canonical_u32(mult),
156        addrs: ExpReverseBitsIo {
157            base: Address(base),
158            exp: exp.into_iter().map(Address).collect(),
159            result: Address(result),
160        },
161    })
162}
163
164#[allow(clippy::too_many_arguments)]
165pub fn fri_fold<F: AbstractField>(
166    z: u32,
167    alpha: u32,
168    x: u32,
169    mat_opening: Vec<u32>,
170    ps_at_z: Vec<u32>,
171    alpha_pow_input: Vec<u32>,
172    ro_input: Vec<u32>,
173    alpha_pow_output: Vec<u32>,
174    ro_output: Vec<u32>,
175    alpha_mults: Vec<u32>,
176    ro_mults: Vec<u32>,
177) -> Instruction<F> {
178    Instruction::FriFold(Box::new(FriFoldInstr {
179        base_single_addrs: FriFoldBaseIo { x: Address(F::from_canonical_u32(x)) },
180        ext_single_addrs: FriFoldExtSingleIo {
181            z: Address(F::from_canonical_u32(z)),
182            alpha: Address(F::from_canonical_u32(alpha)),
183        },
184        ext_vec_addrs: FriFoldExtVecIo {
185            mat_opening: mat_opening
186                .iter()
187                .map(|elm| Address(F::from_canonical_u32(*elm)))
188                .collect(),
189            ps_at_z: ps_at_z.iter().map(|elm| Address(F::from_canonical_u32(*elm))).collect(),
190            alpha_pow_input: alpha_pow_input
191                .iter()
192                .map(|elm| Address(F::from_canonical_u32(*elm)))
193                .collect(),
194            ro_input: ro_input.iter().map(|elm| Address(F::from_canonical_u32(*elm))).collect(),
195            alpha_pow_output: alpha_pow_output
196                .iter()
197                .map(|elm| Address(F::from_canonical_u32(*elm)))
198                .collect(),
199            ro_output: ro_output.iter().map(|elm| Address(F::from_canonical_u32(*elm))).collect(),
200        },
201        alpha_pow_mults: alpha_mults.iter().map(|mult| F::from_canonical_u32(*mult)).collect(),
202        ro_mults: ro_mults.iter().map(|mult| F::from_canonical_u32(*mult)).collect(),
203    }))
204}
205
206pub fn commit_public_values<F: AbstractField>(
207    public_values_a: &RecursionPublicValues<u32>,
208) -> Instruction<F> {
209    let pv_a = public_values_a.to_vec().map(|pv| Address(F::from_canonical_u32(pv)));
210    let pv_address: &RecursionPublicValues<Address<F>> = pv_a.as_slice().borrow();
211
212    Instruction::CommitPublicValues(Box::new(CommitPublicValuesInstr {
213        pv_addrs: pv_address.clone(),
214    }))
215}