1use std::{fmt, fmt::Display};
2
3use itertools::Itertools;
4use openvm_stark_backend::p3_field::Field;
5use serde::{Deserialize, Serialize};
6
7use crate::instruction::{DebugInfo, Instruction};
8
9pub const PC_BITS: usize = 30;
10pub const DEFAULT_PC_STEP: u32 = 4;
13pub const DEFAULT_MAX_NUM_PUBLIC_VALUES: usize = 32;
14pub const MAX_ALLOWED_PC: u32 = (1 << PC_BITS) - 1;
15
16#[derive(Clone, Debug, Default, Serialize, Deserialize)]
17pub struct Program<F> {
18 pub instructions_and_debug_infos: Vec<Option<(Instruction<F>, Option<DebugInfo>)>>,
23 pub step: u32,
24 pub pc_base: u32,
25 pub max_num_public_values: usize,
29}
30
31impl<F: Field> Program<F> {
32 pub fn new_empty(step: u32, pc_base: u32, max_num_public_values: usize) -> Self {
33 Self {
34 instructions_and_debug_infos: vec![],
35 step,
36 pc_base,
37 max_num_public_values,
38 }
39 }
40
41 pub fn new_without_debug_infos(
42 instructions: &[Instruction<F>],
43 step: u32,
44 pc_base: u32,
45 max_num_public_values: usize,
46 ) -> Self {
47 Self {
48 instructions_and_debug_infos: instructions
49 .iter()
50 .map(|instruction| Some((instruction.clone(), None)))
51 .collect(),
52 step,
53 pc_base,
54 max_num_public_values,
55 }
56 }
57
58 pub fn new_without_debug_infos_with_option(
59 instructions: &[Option<Instruction<F>>],
60 step: u32,
61 pc_base: u32,
62 max_num_public_values: usize,
63 ) -> Self {
64 Self {
65 instructions_and_debug_infos: instructions
66 .iter()
67 .map(|instruction| instruction.clone().map(|instruction| (instruction, None)))
68 .collect(),
69 step,
70 pc_base,
71 max_num_public_values,
72 }
73 }
74
75 pub fn from_instructions_and_debug_infos(
78 instructions: &[Instruction<F>],
79 debug_infos: &[Option<DebugInfo>],
80 ) -> Self {
81 Self {
82 instructions_and_debug_infos: instructions
83 .iter()
84 .zip_eq(debug_infos.iter())
85 .map(|(instruction, debug_info)| Some((instruction.clone(), debug_info.clone())))
86 .collect(),
87 step: DEFAULT_PC_STEP,
88 pc_base: 0,
89 max_num_public_values: DEFAULT_MAX_NUM_PUBLIC_VALUES,
90 }
91 }
92
93 pub fn strip_debug_infos(self) -> Self {
94 Self {
95 instructions_and_debug_infos: self
96 .instructions_and_debug_infos
97 .into_iter()
98 .map(|opt| opt.map(|(ins, _)| (ins, None)))
99 .collect(),
100 ..self
101 }
102 }
103
104 pub fn from_instructions(instructions: &[Instruction<F>]) -> Self {
105 Self::new_without_debug_infos(
106 instructions,
107 DEFAULT_PC_STEP,
108 0,
109 DEFAULT_MAX_NUM_PUBLIC_VALUES,
110 )
111 }
112
113 pub fn len(&self) -> usize {
114 self.instructions_and_debug_infos.len()
115 }
116
117 pub fn is_empty(&self) -> bool {
118 self.instructions_and_debug_infos.is_empty()
119 }
120
121 pub fn defined_instructions(&self) -> Vec<Instruction<F>> {
122 self.instructions_and_debug_infos
123 .iter()
124 .flatten()
125 .map(|(instruction, _)| instruction.clone())
126 .collect()
127 }
128
129 pub fn num_defined_instructions(&self) -> usize {
131 self.defined_instructions().len()
132 }
133
134 pub fn debug_infos(&self) -> Vec<Option<DebugInfo>> {
135 self.instructions_and_debug_infos
136 .iter()
137 .flatten()
138 .map(|(_, debug_info)| debug_info.clone())
139 .collect()
140 }
141
142 pub fn enumerate_by_pc(&self) -> Vec<(u32, Instruction<F>, Option<DebugInfo>)> {
143 self.instructions_and_debug_infos
144 .iter()
145 .enumerate()
146 .flat_map(|(index, option)| {
147 option.clone().map(|(instruction, debug_info)| {
148 (
149 self.pc_base + (self.step * (index as u32)),
150 instruction,
151 debug_info,
152 )
153 })
154 })
155 .collect()
156 }
157
158 pub fn get_instruction_and_debug_info(
160 &self,
161 index: usize,
162 ) -> Option<&(Instruction<F>, Option<DebugInfo>)> {
163 self.instructions_and_debug_infos
164 .get(index)
165 .and_then(|x| x.as_ref())
166 }
167
168 pub fn push_instruction_and_debug_info(
169 &mut self,
170 instruction: Instruction<F>,
171 debug_info: Option<DebugInfo>,
172 ) {
173 self.instructions_and_debug_infos
174 .push(Some((instruction, debug_info)));
175 }
176
177 pub fn push_instruction(&mut self, instruction: Instruction<F>) {
178 self.push_instruction_and_debug_info(instruction, None);
179 }
180
181 pub fn append(&mut self, other: Program<F>) {
182 self.instructions_and_debug_infos
183 .extend(other.instructions_and_debug_infos);
184 }
185}
186impl<F: Field> Display for Program<F> {
187 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
188 for instruction in self.defined_instructions().iter() {
189 let Instruction {
190 opcode,
191 a,
192 b,
193 c,
194 d,
195 e,
196 f,
197 g,
198 } = instruction;
199 writeln!(
200 formatter,
201 "{:?} {} {} {} {} {} {} {}",
202 opcode, a, b, c, d, e, f, g,
203 )?;
204 }
205 Ok(())
206 }
207}
208
209pub fn display_program_with_pc<F: Field>(program: &Program<F>) {
210 for (pc, instruction) in program.defined_instructions().iter().enumerate() {
211 let Instruction {
212 opcode,
213 a,
214 b,
215 c,
216 d,
217 e,
218 f,
219 g,
220 } = instruction;
221 println!(
222 "{} | {:?} {} {} {} {} {} {} {}",
223 pc, opcode, a, b, c, d, e, f, g
224 );
225 }
226}