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 op_eval_circuit(&mut self, err_ctx: &impl ErrorContext) -> Result<(), ExecutionError> {
31 let num_eval = self.stack_get(2);
32 let num_read = self.stack_get(1);
33 let ptr = self.stack_get(0);
34 let ctx = self.ctx;
35 let circuit_evaluation =
36 eval_circuit_fast_(ctx, ptr, self.clk, num_read, num_eval, &mut self.memory, err_ctx)?;
37 self.ace.add_circuit_evaluation(self.clk, circuit_evaluation);
38
39 Ok(())
40 }
41}
42
43#[allow(clippy::too_many_arguments)]
45pub fn eval_circuit_fast_(
46 ctx: ContextId,
47 ptr: Felt,
48 clk: RowIndex,
49 num_vars: Felt,
50 num_eval: Felt,
51 mem: &mut Memory,
52 err_ctx: &impl ErrorContext,
53) -> Result<CircuitEvaluation, ExecutionError> {
54 let num_vars = num_vars.as_int();
55 let num_eval = num_eval.as_int();
56
57 let num_wires = num_vars + num_eval;
58 if num_wires > MAX_NUM_ACE_WIRES as u64 {
59 return Err(ExecutionError::failed_arithmetic_evaluation(
60 err_ctx,
61 AceError::TooManyWires(num_wires),
62 ));
63 }
64
65 if !num_vars.is_multiple_of(2) || num_vars == 0 {
69 return Err(ExecutionError::failed_arithmetic_evaluation(
70 err_ctx,
71 AceError::NumVarIsNotWordAlignedOrIsEmpty(num_vars),
72 ));
73 }
74 if !num_eval.is_multiple_of(4) || num_eval == 0 {
75 return Err(ExecutionError::failed_arithmetic_evaluation(
76 err_ctx,
77 AceError::NumEvalIsNotWordAlignedOrIsEmpty(num_eval),
78 ));
79 }
80
81 let num_read_rows = num_vars as u32 / 2;
83 let num_eval_rows = num_eval as u32;
84
85 let mut evaluation_context = CircuitEvaluation::new(ctx, clk, num_read_rows, num_eval_rows);
86
87 let mut ptr = ptr;
88 for _ in 0..num_read_rows {
90 let word = mem.read_word(ctx, ptr, clk, err_ctx).map_err(ExecutionError::MemoryError)?;
91 evaluation_context.do_read(ptr, word)?;
92 ptr += PTR_OFFSET_WORD;
93 }
94 for _ in 0..num_eval_rows {
96 let instruction =
97 mem.read_element(ctx, ptr, err_ctx).map_err(ExecutionError::MemoryError)?;
98 evaluation_context.do_eval(ptr, instruction, err_ctx)?;
99 ptr += PTR_OFFSET_ELEM;
100 }
101
102 if !evaluation_context.output_value().is_some_and(|eval| eval == QuadFelt::ZERO) {
104 return Err(ExecutionError::failed_arithmetic_evaluation(
105 err_ctx,
106 AceError::CircuitNotEvaluateZero,
107 ));
108 }
109
110 Ok(evaluation_context)
111}