miden_ace_codegen/layout/
plan.rs1use super::InputKey;
2use crate::EXT_DEGREE;
3
4#[derive(Debug, Clone, Copy, PartialEq, Eq)]
6pub(crate) struct InputRegion {
7 pub offset: usize,
8 pub width: usize,
9}
10
11impl InputRegion {
12 pub fn index(&self, local: usize) -> Option<usize> {
14 (local < self.width).then(|| self.offset + local)
15 }
16}
17
18#[derive(Debug, Clone, Copy)]
20pub struct InputCounts {
21 pub width: usize,
23 pub aux_width: usize,
25 pub num_aux_boundary: usize,
27 pub num_public: usize,
29 pub num_vlpi: usize,
33 pub num_randomness: usize,
35 pub num_periodic: usize,
37 pub num_quotient_chunks: usize,
39}
40
41#[derive(Debug, Clone, Copy, PartialEq, Eq)]
43pub(crate) struct LayoutRegions {
44 pub public_values: InputRegion,
46 pub vlpi_reductions: InputRegion,
48 pub randomness: InputRegion,
50 pub main_curr: InputRegion,
52 pub aux_curr: InputRegion,
54 pub quotient_curr: InputRegion,
56 pub main_next: InputRegion,
58 pub aux_next: InputRegion,
60 pub quotient_next: InputRegion,
62 pub aux_bus_boundary: InputRegion,
64 pub stark_vars: InputRegion,
66}
67
68#[derive(Debug, Clone, Copy, PartialEq, Eq)]
78pub(crate) struct StarkVarIndices {
79 pub alpha: usize,
82 pub z_pow_n: usize,
84 pub z_k: usize,
86 pub is_first: usize,
88 pub is_last: usize,
90 pub is_transition: usize,
92 pub gamma: usize,
94
95 pub weight0: usize,
98 pub f: usize,
100 pub s0: usize,
102
103 pub multi_air_beta_core: Option<usize>,
107 pub multi_air_beta_chip: Option<usize>,
108 pub is_first_core: Option<usize>,
110 pub is_last_core: Option<usize>,
111 pub is_transition_core: Option<usize>,
112 pub is_first_chip: Option<usize>,
114 pub is_last_chip: Option<usize>,
115 pub is_transition_chip: Option<usize>,
116}
117
118#[derive(Debug, Clone)]
123pub struct InputLayout {
124 pub(crate) regions: LayoutRegions,
126 pub(crate) aux_rand_alpha: usize,
128 pub(crate) aux_rand_beta: usize,
130 pub(crate) vlpi_stride: usize,
132 pub(crate) stark: StarkVarIndices,
134 pub total_inputs: usize,
136 pub counts: InputCounts,
138}
139
140impl InputLayout {
141 pub(crate) fn mapper(&self) -> super::InputKeyMapper<'_> {
142 super::InputKeyMapper { layout: self }
143 }
144
145 pub fn index(&self, key: InputKey) -> Option<usize> {
147 self.mapper().index_of(key)
148 }
149
150 pub(crate) fn validate(&self) {
152 let mut max_end = 0usize;
153 for region in [
154 self.regions.public_values,
155 self.regions.vlpi_reductions,
156 self.regions.randomness,
157 self.regions.main_curr,
158 self.regions.aux_curr,
159 self.regions.quotient_curr,
160 self.regions.main_next,
161 self.regions.aux_next,
162 self.regions.quotient_next,
163 self.regions.aux_bus_boundary,
164 self.regions.stark_vars,
165 ] {
166 max_end = max_end.max(region.offset.saturating_add(region.width));
167 }
168
169 assert!(max_end <= self.total_inputs, "regions exceed total_inputs");
170
171 let aux_coord_width = self.counts.aux_width * EXT_DEGREE;
172 assert_eq!(self.regions.aux_curr.width, aux_coord_width, "aux_curr width mismatch");
173 assert_eq!(self.regions.aux_next.width, aux_coord_width, "aux_next width mismatch");
174
175 let quotient_width = self.counts.num_quotient_chunks * EXT_DEGREE;
176 assert_eq!(
177 self.regions.quotient_curr.width, quotient_width,
178 "quotient_curr width mismatch"
179 );
180 assert_eq!(
181 self.regions.quotient_next.width, quotient_width,
182 "quotient_next width mismatch"
183 );
184 assert_eq!(
185 self.regions.aux_bus_boundary.width, self.counts.num_aux_boundary,
186 "aux bus boundary width mismatch"
187 );
188
189 let stark_start = self.regions.stark_vars.offset;
190 let stark_end = stark_start + self.regions.stark_vars.width;
191 let check = |name: &str, idx: usize| {
192 assert!(idx >= stark_start && idx < stark_end, "stark var {name} out of range");
193 };
194 check("alpha", self.stark.alpha);
196 check("z_pow_n", self.stark.z_pow_n);
197 check("z_k", self.stark.z_k);
198 check("is_first", self.stark.is_first);
199 check("is_last", self.stark.is_last);
200 check("is_transition", self.stark.is_transition);
201 check("gamma", self.stark.gamma);
202 check("weight0", self.stark.weight0);
204 check("f", self.stark.f);
205 check("s0", self.stark.s0);
206 if let Some(idx) = self.stark.multi_air_beta_core {
207 check("multi_air_beta_core", idx);
208 }
209 if let Some(idx) = self.stark.multi_air_beta_chip {
210 check("multi_air_beta_chip", idx);
211 }
212 if let Some(idx) = self.stark.is_first_core {
213 check("is_first_core", idx);
214 }
215 if let Some(idx) = self.stark.is_last_core {
216 check("is_last_core", idx);
217 }
218 if let Some(idx) = self.stark.is_transition_core {
219 check("is_transition_core", idx);
220 }
221 if let Some(idx) = self.stark.is_first_chip {
222 check("is_first_chip", idx);
223 }
224 if let Some(idx) = self.stark.is_last_chip {
225 check("is_last_chip", idx);
226 }
227 if let Some(idx) = self.stark.is_transition_chip {
228 check("is_transition_chip", idx);
229 }
230
231 let rand_start = self.regions.randomness.offset;
232 let rand_end = rand_start + self.regions.randomness.width;
233 assert!(
234 self.aux_rand_alpha >= rand_start && self.aux_rand_alpha < rand_end,
235 "aux_rand_alpha out of randomness region"
236 );
237 assert!(
238 self.aux_rand_beta >= rand_start && self.aux_rand_beta < rand_end,
239 "aux_rand_beta out of randomness region"
240 );
241 }
242}