Skip to main content

sp1_core_machine/program/
instruction.rs

1use slop_algebra::PrimeField;
2use sp1_core_executor::{Instruction, Register};
3use sp1_derive::AlignedBorrow;
4use sp1_hypercube::Word;
5use std::{iter::once, mem::size_of, vec::IntoIter};
6
7pub const NUM_INSTRUCTION_COLS: usize = size_of::<InstructionCols<u8>>();
8
9/// The column layout for instructions.
10#[derive(AlignedBorrow, Clone, Copy, Default, Debug)]
11#[repr(C)]
12pub struct InstructionCols<T> {
13    /// The opcode for this cycle.
14    pub opcode: T,
15
16    /// The first operand for this instruction.
17    pub op_a: T,
18
19    /// The second operand for this instruction.
20    pub op_b: Word<T>,
21
22    /// The third operand for this instruction.
23    pub op_c: Word<T>,
24
25    /// Flags to indicate if op_a is register 0.
26    pub op_a_0: T,
27
28    /// Whether op_b is an immediate value.
29    pub imm_b: T,
30
31    /// Whether op_c is an immediate value.
32    pub imm_c: T,
33}
34
35impl<F: PrimeField> InstructionCols<F> {
36    pub fn populate(&mut self, instruction: &Instruction) {
37        self.opcode = instruction.opcode.as_field::<F>();
38        self.op_a = F::from_canonical_u8(instruction.op_a);
39        self.op_b = instruction.op_b.into();
40        self.op_c = instruction.op_c.into();
41
42        self.op_a_0 = F::from_bool(instruction.op_a == Register::X0 as u8);
43        self.imm_b = F::from_bool(instruction.imm_b);
44        self.imm_c = F::from_bool(instruction.imm_c);
45    }
46}
47
48impl<T> IntoIterator for InstructionCols<T> {
49    type Item = T;
50    type IntoIter = IntoIter<T>;
51
52    fn into_iter(self) -> Self::IntoIter {
53        once(self.opcode)
54            .chain(once(self.op_a))
55            .chain(self.op_b)
56            .chain(self.op_c)
57            .chain(once(self.op_a_0))
58            .chain(once(self.imm_b))
59            .chain(once(self.imm_c))
60            .collect::<Vec<_>>()
61            .into_iter()
62    }
63}