Source code for zisk/state-machines/main/src/main_planner.rs
1//! The `MainPlanner` module defines a planner for the Main State Machine.
2//!
3//! It generates execution plans for segments of the main trace, mapping each segment
4//! to a specific `Plan` instance.
5
6use std::any::Any;
7
8use asm_runner::MinimalTraces;
9use fields::PrimeField64;
10use zisk_common::{BusDeviceMetrics, CheckPoint, ChunkId, InstanceType, Metrics, Plan, SegmentId};
11use zisk_pil::{MainTrace, MAIN_AIR_IDS, ZISK_AIRGROUP_ID};
12
13use crate::MainCounter;
14
15/// The `MainPlanner` struct generates execution plans for the Main State Machine.
16///
17/// It organizes the execution flow by creating a `Plan` instance for each segment
18/// of the main trace, associating it with the corresponding segment ID.
19pub struct MainPlanner {}
20
21impl MainPlanner {
22 /// Generates execution plans for the Main State Machine.
23 ///
24 /// This method creates a `Plan` for each segment of the provided traces, associating
25 /// the segment ID with the corresponding execution plan.
26 ///
27 /// # Arguments
28 /// * `min_traces` - A slice of `EmuTrace` instances representing the segments to be planned.
29 /// * `main_counters` - A vector of main counters, each associated with a specific chunk ID.
30 /// * `min_traces_size` - The size of the minimal traces.
31 ///
32 /// # Returns
33 /// A vector of `Plan` instances, each corresponding to a segment of the main trace.
34 pub fn plan<F: PrimeField64>(
35 min_traces: &MinimalTraces,
36 main_counters: Vec<(ChunkId, Box<dyn BusDeviceMetrics>)>,
37 min_traces_size: u64,
38 ) -> (Vec<Plan>, Vec<(u64, u32)>) {
39 let min_traces = match min_traces {
40 MinimalTraces::AsmEmuTrace(asm_min_traces) => &asm_min_traces.vec_chunks,
41 MinimalTraces::EmuTrace(vec_chunks) => vec_chunks,
42 MinimalTraces::None => {
43 panic!("Minimal traces are required for planning the main state machine.");
44 }
45 };
46
47 let num_rows = MainTrace::<F>::NUM_ROWS as u64;
48
49 let mut publics = Vec::new();
50
51 main_counters.iter().for_each(|(_, counter)| {
52 let reg_counter = Metrics::as_any(&**counter).downcast_ref::<MainCounter>().unwrap();
53 publics.extend_from_slice(®_counter.publics);
54 });
55
56 assert!(num_rows.is_power_of_two());
57 assert!(min_traces_size.is_power_of_two());
58 assert!(num_rows >= min_traces_size);
59
60 // This is the number of minimal traces wrapped in a main trace
61 let num_within = num_rows / min_traces_size;
62 let num_instances = (min_traces.len() as f64 / num_within as f64).ceil() as usize;
63
64 let plans: Vec<Plan> = (0..num_instances)
65 .map(|segment_id| {
66 Plan::new(
67 ZISK_AIRGROUP_ID,
68 MAIN_AIR_IDS[0],
69 Some(SegmentId(segment_id)),
70 InstanceType::Instance,
71 CheckPoint::Single(ChunkId(segment_id)),
72 Some(Box::new(segment_id == num_instances - 1) as Box<dyn Any>),
73 )
74 })
75 .collect();
76
77 (plans, publics)
78 }
79}