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_randomness: usize,
31 pub num_periodic: usize,
33 pub num_quotient_chunks: usize,
35}
36
37#[derive(Debug, Clone, Copy, PartialEq, Eq)]
39pub(crate) struct LayoutRegions {
40 pub public_values: InputRegion,
42 pub randomness: InputRegion,
44 pub main_curr: InputRegion,
46 pub aux_curr: InputRegion,
48 pub quotient_curr: InputRegion,
50 pub main_next: InputRegion,
52 pub aux_next: InputRegion,
54 pub quotient_next: InputRegion,
56 pub aux_bus_boundary: InputRegion,
58 pub stark_vars: InputRegion,
60}
61
62#[derive(Debug, Clone, Copy, PartialEq, Eq)]
72pub(crate) struct StarkVarIndices {
73 pub alpha: usize,
76 pub z_pow_n: usize,
78 pub z_k: usize,
80 pub is_first: usize,
82 pub is_last: usize,
84 pub is_transition: usize,
86 pub reserved: usize,
88
89 pub weight0: usize,
92 pub f: usize,
94 pub s0: usize,
96
97 pub multi_air: Option<MultiAirVarIndices>,
100}
101
102#[derive(Debug, Clone, Copy, PartialEq, Eq)]
108pub(crate) struct MultiAirVarIndices {
109 pub base: usize,
111 pub num_airs: usize,
113}
114
115impl MultiAirVarIndices {
116 pub fn beta(&self, air: usize) -> Option<usize> {
118 (air < self.num_airs).then(|| self.base + air)
119 }
120
121 pub fn selector(&self, air: usize, sel: usize) -> Option<usize> {
124 (air < self.num_airs && sel < 3).then(|| self.base + self.num_airs + 3 * air + sel)
125 }
126
127 pub fn width(&self) -> usize {
129 4 * self.num_airs
130 }
131}
132
133#[derive(Debug, Clone)]
138pub struct InputLayout {
139 pub(crate) regions: LayoutRegions,
141 pub(crate) aux_rand_alpha: usize,
143 pub(crate) aux_rand_beta: usize,
145 pub(crate) stark: StarkVarIndices,
147 pub total_inputs: usize,
149 pub counts: InputCounts,
151}
152
153impl InputLayout {
154 pub(crate) fn mapper(&self) -> super::InputKeyMapper<'_> {
155 super::InputKeyMapper { layout: self }
156 }
157
158 pub fn index(&self, key: InputKey) -> Option<usize> {
160 self.mapper().index_of(key)
161 }
162
163 pub(crate) fn validate(&self) {
165 let mut max_end = 0usize;
166 for region in [
167 self.regions.public_values,
168 self.regions.randomness,
169 self.regions.main_curr,
170 self.regions.aux_curr,
171 self.regions.quotient_curr,
172 self.regions.main_next,
173 self.regions.aux_next,
174 self.regions.quotient_next,
175 self.regions.aux_bus_boundary,
176 self.regions.stark_vars,
177 ] {
178 max_end = max_end.max(region.offset.saturating_add(region.width));
179 }
180
181 assert!(max_end <= self.total_inputs, "regions exceed total_inputs");
182
183 let aux_coord_width = self.counts.aux_width * EXT_DEGREE;
184 assert_eq!(self.regions.aux_curr.width, aux_coord_width, "aux_curr width mismatch");
185 assert_eq!(self.regions.aux_next.width, aux_coord_width, "aux_next width mismatch");
186
187 let quotient_width = self.counts.num_quotient_chunks * EXT_DEGREE;
188 assert_eq!(
189 self.regions.quotient_curr.width, quotient_width,
190 "quotient_curr width mismatch"
191 );
192 assert_eq!(
193 self.regions.quotient_next.width, quotient_width,
194 "quotient_next width mismatch"
195 );
196 assert_eq!(
197 self.regions.aux_bus_boundary.width, self.counts.num_aux_boundary,
198 "aux bus boundary width mismatch"
199 );
200
201 let stark_start = self.regions.stark_vars.offset;
202 let stark_end = stark_start + self.regions.stark_vars.width;
203 let check = |name: &str, idx: usize| {
204 assert!(idx >= stark_start && idx < stark_end, "stark var {name} out of range");
205 };
206 check("alpha", self.stark.alpha);
208 check("z_pow_n", self.stark.z_pow_n);
209 check("z_k", self.stark.z_k);
210 check("is_first", self.stark.is_first);
211 check("is_last", self.stark.is_last);
212 check("is_transition", self.stark.is_transition);
213 check("reserved", self.stark.reserved);
214 check("weight0", self.stark.weight0);
216 check("f", self.stark.f);
217 check("s0", self.stark.s0);
218 if let Some(multi_air) = &self.stark.multi_air {
219 check("multi_air block start", multi_air.base);
220 check("multi_air block end", multi_air.base + multi_air.width() - 1);
221 }
222
223 let rand_start = self.regions.randomness.offset;
224 let rand_end = rand_start + self.regions.randomness.width;
225 assert!(
226 self.aux_rand_alpha >= rand_start && self.aux_rand_alpha < rand_end,
227 "aux_rand_alpha out of randomness region"
228 );
229 assert!(
230 self.aux_rand_beta >= rand_start && self.aux_rand_beta < rand_end,
231 "aux_rand_beta out of randomness region"
232 );
233 }
234}