Skip to main content

miden_processor/trace/chiplets/ace/
mod.rs

1use alloc::collections::BTreeMap;
2
3use miden_air::trace::{RowIndex, chiplets::ace::ACE_CHIPLET_NUM_COLS};
4use miden_core::{Felt, field::PrimeCharacteristicRing};
5
6use crate::trace::ChipletTraceFragment;
7
8mod trace;
9pub use trace::CircuitEvaluation;
10
11mod instruction;
12#[cfg(test)]
13mod tests;
14
15pub const PTR_OFFSET_ELEM: Felt = Felt::ONE;
16pub const PTR_OFFSET_WORD: Felt = Felt::new_unchecked(4);
17pub const MAX_NUM_ACE_WIRES: u32 = instruction::MAX_ID;
18
19/// Maximum combined number of READ and EVAL wires accepted by one `eval_circuit` operation.
20///
21/// Bounds host allocation and work before circuit evaluation begins. This should accommodate
22/// the ACE circuits of both the VM and PVM recursive verifiers, currently 6,044 and 13,912 wires
23/// respectively (see `sys/{vm,pvm}/constraints_eval.masm` in the core library).
24pub const MAX_EVAL_CIRCUIT_WIRES: u32 = 1 << 15;
25
26/// Maximum number of `eval_circuit` invocations recorded in an execution witness.
27///
28/// Together with [`MAX_EVAL_CIRCUIT_WIRES`], bounds cumulative ACE work and witness storage
29/// during witness collection. Execution without tracing only enforces the per-call wire limit.
30pub const MAX_EVAL_CIRCUIT_INVOCATIONS: u32 = 1 << 5;
31
32/// Arithmetic circuit evaluation (ACE) chiplet.
33///
34/// This is a VM chiplet used to evaluate arithmetic circuits given some input, which is equivalent
35/// to evaluating some multi-variate polynomial at a tuple representing the input.
36///
37/// During the course of the VM execution, we keep track of all calls to the ACE chiplet in an
38/// [`CircuitEvaluation`] per call. This is then used to generate the full trace of the ACE chiplet.
39#[derive(Debug, Default)]
40pub struct Ace {
41    circuit_evaluations: BTreeMap<RowIndex, CircuitEvaluation>,
42}
43
44impl Ace {
45    /// Gets the total trace length of the ACE chiplet.
46    pub(crate) fn trace_len(&self) -> usize {
47        self.circuit_evaluations.values().map(CircuitEvaluation::num_rows).sum()
48    }
49
50    /// Fills the portion of the main trace allocated to the ACE chiplet.
51    pub(crate) fn fill_trace(self, trace: &mut ChipletTraceFragment) {
52        // make sure fragment dimensions are consistent with the dimensions of this trace
53        debug_assert_eq!(self.trace_len(), trace.len(), "inconsistent trace lengths");
54        debug_assert_eq!(ACE_CHIPLET_NUM_COLS, trace.width(), "inconsistent trace widths");
55
56        // Row-major scratch: `ACE_CHIPLET_NUM_COLS` contiguous cells per row.
57        let mut gen_trace = Felt::zero_vec(self.trace_len() * ACE_CHIPLET_NUM_COLS);
58
59        let mut offset = 0;
60        for eval_ctx in self.circuit_evaluations.into_values() {
61            eval_ctx.fill(offset, &mut gen_trace);
62            offset += eval_ctx.num_rows();
63        }
64
65        trace.copy_rows_from(&gen_trace);
66    }
67
68    /// Adds an entry resulting from a call to the ACE chiplet.
69    pub(crate) fn add_circuit_evaluation(
70        &mut self,
71        clk: RowIndex,
72        circuit_eval: CircuitEvaluation,
73    ) {
74        self.circuit_evaluations.insert(clk, circuit_eval);
75    }
76}