miden_processor/fast/
circuit_eval.rs1use miden_air::RowIndex;
2use miden_core::{Felt, FieldElement, QuadFelt};
3
4use super::{FastProcessor, memory::Memory};
5use crate::{
6 ContextId, ExecutionError,
7 chiplets::{CircuitEvaluation, MAX_NUM_ACE_WIRES, PTR_OFFSET_ELEM, PTR_OFFSET_WORD},
8 errors::{AceError, ErrorContext},
9};
10
11impl FastProcessor {
12 pub fn arithmetic_circuit_eval(
31 &mut self,
32 op_idx: usize,
33 err_ctx: &impl ErrorContext,
34 ) -> Result<(), ExecutionError> {
35 let num_eval_rows = self.stack_get(2);
36 let num_read_rows = self.stack_get(1);
37 let ptr = self.stack_get(0);
38 let ctx = self.ctx;
39 let clk = self.clk;
40 let circuit_evaluation = eval_circuit_fast_(
41 ctx,
42 ptr,
43 clk,
44 num_read_rows,
45 num_eval_rows,
46 &mut self.memory,
47 op_idx,
48 err_ctx,
49 )?;
50 self.ace.add_circuit_evaluation(clk, circuit_evaluation);
51
52 Ok(())
53 }
54}
55
56#[allow(clippy::too_many_arguments)]
58pub fn eval_circuit_fast_(
59 ctx: ContextId,
60 ptr: Felt,
61 clk: RowIndex,
62 num_vars: Felt,
63 num_eval: Felt,
64 mem: &mut Memory,
65 op_idx: usize,
66 err_ctx: &impl ErrorContext,
67) -> Result<CircuitEvaluation, ExecutionError> {
68 let num_vars = num_vars.as_int();
69 let num_eval = num_eval.as_int();
70
71 let num_wires = num_vars + num_eval;
72 if num_wires > MAX_NUM_ACE_WIRES as u64 {
73 return Err(ExecutionError::failed_arithmetic_evaluation(
74 err_ctx,
75 AceError::TooManyWires(num_wires),
76 ));
77 }
78
79 if num_vars % 2 != 0 || num_vars == 0 {
83 return Err(ExecutionError::failed_arithmetic_evaluation(
84 err_ctx,
85 AceError::NumVarIsNotWordAlignedOrIsEmpty(num_vars),
86 ));
87 }
88 if num_eval % 4 != 0 || num_eval == 0 {
89 return Err(ExecutionError::failed_arithmetic_evaluation(
90 err_ctx,
91 AceError::NumEvalIsNotWordAlignedOrIsEmpty(num_eval),
92 ));
93 }
94
95 let num_read_rows = num_vars as u32 / 2;
97 let num_eval_rows = num_eval as u32;
98
99 let mut evaluation_context =
100 CircuitEvaluation::new(ctx, clk + op_idx, num_read_rows, num_eval_rows);
101
102 let mut ptr = ptr;
103 for _ in 0..num_read_rows {
105 let word = mem
106 .read_word(ctx, ptr, clk + op_idx, err_ctx)
107 .map_err(ExecutionError::MemoryError)?;
108 evaluation_context.do_read(ptr, word)?;
109 ptr += PTR_OFFSET_WORD;
110 }
111 for _ in 0..num_eval_rows {
113 let instruction =
114 mem.read_element(ctx, ptr, err_ctx).map_err(ExecutionError::MemoryError)?;
115 evaluation_context.do_eval(ptr, instruction, err_ctx)?;
116 ptr += PTR_OFFSET_ELEM;
117 }
118
119 if !evaluation_context.output_value().is_some_and(|eval| eval == QuadFelt::ZERO) {
121 return Err(ExecutionError::failed_arithmetic_evaluation(
122 err_ctx,
123 AceError::CircuitNotEvaluateZero,
124 ));
125 }
126
127 Ok(evaluation_context)
128}