miden_processor/fast/
tracer.rs

1use alloc::sync::Arc;
2
3use miden_air::trace::{chiplets::hasher::STATE_WIDTH, rows::RowIndex};
4use miden_core::{
5    Felt, Word,
6    crypto::merkle::MerklePath,
7    mast::{MastForest, MastNodeId},
8};
9
10use crate::{
11    chiplets::CircuitEvaluation,
12    continuation_stack::ContinuationStack,
13    fast::{FastProcessor, trace_state::NodeExecutionState},
14    system::ContextId,
15};
16
17/// A trait for tracing the execution of a [FastProcessor].
18pub trait Tracer {
19    /// Signals the start of a new clock cycle.
20    ///
21    /// This is guaranteed to be called before executing the operation at the given clock cycle.
22    /// Additionally, [miden_core::mast::ExternalNode] nodes are guaranteed to be resolved before
23    /// this method is called.
24    fn start_clock_cycle(
25        &mut self,
26        processor: &FastProcessor,
27        execution_state: NodeExecutionState,
28        continuation_stack: &mut ContinuationStack,
29        current_forest: &Arc<MastForest>,
30    );
31
32    /// Records and replays the resolutions of [crate::host::AsyncHost::get_mast_forest] or
33    /// [crate::host::SyncHost::get_mast_forest].
34    ///
35    /// Note that when execution encounters a [miden_core::mast::ExternalNode], the external node
36    /// gets resolved to the MAST node it refers to in the new MAST forest, without consuming the
37    /// clock cycle (or writing anything to the trace). Hence, a clock cycle where execution
38    /// encounters an external node effectively has 2 nodes associated with it.
39    /// [Tracer::start_clock_cycle] is called on the resolved node (i.e. *not* the external node).
40    /// This method is called on the external node before it is resolved, and hence is guaranteed to
41    /// be called before [Tracer::start_clock_cycle] for clock cycles involving an external node.
42    fn record_mast_forest_resolution(&mut self, node_id: MastNodeId, forest: &Arc<MastForest>);
43
44    // HASHER METHODS
45    // -----------------------------------------------
46
47    /// Records the result of a call to `Hasher::permute()`.
48    fn record_hasher_permute(
49        &mut self,
50        input_state: [Felt; STATE_WIDTH],
51        output_state: [Felt; STATE_WIDTH],
52    );
53
54    /// Records the result of a call to `Hasher::build_merkle_root()`.
55    ///
56    /// The `path` is an `Option` to support environments where the `Hasher` is not present, such as
57    /// in the context of parallel trace generation.
58    fn record_hasher_build_merkle_root(
59        &mut self,
60        node: Word,
61        path: Option<&MerklePath>,
62        index: Felt,
63        output_root: Word,
64    );
65
66    /// Records the result of a call to `Hasher::update_merkle_root()`.
67    ///
68    /// The `path` is an `Option` to support environments where the `Hasher` is not present, such as
69    /// in the context of parallel trace generation.
70    fn record_hasher_update_merkle_root(
71        &mut self,
72        old_value: Word,
73        new_value: Word,
74        path: Option<&MerklePath>,
75        index: Felt,
76        old_root: Word,
77        new_root: Word,
78    );
79
80    // MEMORY METHODS
81    // -----------------------------------------------
82
83    /// Records the element read from memory at the given address.
84    fn record_memory_read_element(
85        &mut self,
86        element: Felt,
87        addr: Felt,
88        ctx: ContextId,
89        clk: RowIndex,
90    );
91
92    /// Records the word read from memory at the given address.
93    fn record_memory_read_word(&mut self, word: Word, addr: Felt, ctx: ContextId, clk: RowIndex);
94
95    /// Records the element written to memory at the given address.
96    fn record_memory_write_element(
97        &mut self,
98        element: Felt,
99        addr: Felt,
100        ctx: ContextId,
101        clk: RowIndex,
102    );
103
104    /// Records the word written to memory at the given address.
105    fn record_memory_write_word(&mut self, word: Word, addr: Felt, ctx: ContextId, clk: RowIndex);
106
107    // ADVICE PROVIDER METHODS
108    // -----------------------------------------------
109
110    /// Records the value returned by a [crate::host::advice::AdviceProvider::pop_stack] operation.
111    fn record_advice_pop_stack(&mut self, value: Felt);
112    /// Records the value returned by a [crate::host::advice::AdviceProvider::pop_stack_word]
113    /// operation.
114    fn record_advice_pop_stack_word(&mut self, word: Word);
115    /// Records the value returned by a [crate::host::advice::AdviceProvider::pop_stack_dword]
116    /// operation.
117    fn record_advice_pop_stack_dword(&mut self, words: [Word; 2]);
118
119    // U32 METHODS
120    // -----------------------------------------------
121
122    /// Records the operands of a u32and operation.
123    fn record_u32and(&mut self, a: Felt, b: Felt);
124
125    /// Records the operands of a u32xor operation.
126    fn record_u32xor(&mut self, a: Felt, b: Felt);
127
128    /// Records the high and low 32-bit limbs of the result of a u32 operation for the purposes of
129    /// the range checker. This is expected to result in four 16-bit range checks.
130    fn record_u32_range_checks(&mut self, clk: RowIndex, u32_lo: Felt, u32_hi: Felt);
131
132    // KERNEL METHODS
133    // -----------------------------------------------
134
135    /// Records the procedure hash of a syscall.
136    fn record_kernel_proc_access(&mut self, proc_hash: Word);
137
138    // ACE CHIPLET METHODS
139    // -----------------------------------------------
140
141    /// Records the evaluation of a circuit.
142    fn record_circuit_evaluation(&mut self, clk: RowIndex, circuit_eval: CircuitEvaluation);
143
144    // MISCELLANEOUS
145    // -----------------------------------------------
146
147    /// Signals that the processor clock is being incremented.
148    fn increment_clk(&mut self);
149
150    /// Signals that the stack depth is incremented as a result of pushing a new element.
151    fn increment_stack_size(&mut self, processor: &FastProcessor);
152
153    /// Signals that the stack depth is decremented as a result of popping an element off the stack.
154    ///
155    /// Note that if the stack depth is already [miden_core::stack::MIN_STACK_DEPTH], then the stack
156    /// depth is unchanged; the top element is popped off, and a ZERO is shifted in at the bottom.
157    fn decrement_stack_size(&mut self);
158
159    /// Signals the start of a new execution context, as a result of a CALL, SYSCALL or DYNCALL
160    /// operation being executed.
161    fn start_context(&mut self);
162
163    /// Signals the end of an execution context, as a result of an END operation associated with a
164    /// CALL, SYSCALL or DYNCALL.
165    fn restore_context(&mut self);
166}
167
168/// A [Tracer] that does nothing.
169pub struct NoopTracer;
170
171impl Tracer for NoopTracer {
172    #[inline(always)]
173    fn start_clock_cycle(
174        &mut self,
175        _processor: &FastProcessor,
176        _execution_state: NodeExecutionState,
177        _continuation_stack: &mut ContinuationStack,
178        _current_forest: &Arc<MastForest>,
179    ) {
180        // do nothing
181    }
182
183    #[inline(always)]
184    fn record_mast_forest_resolution(&mut self, _node_id: MastNodeId, _forest: &Arc<MastForest>) {
185        // do nothing
186    }
187
188    #[inline(always)]
189    fn record_hasher_permute(
190        &mut self,
191        _input_state: [Felt; STATE_WIDTH],
192        _output_state: [Felt; STATE_WIDTH],
193    ) {
194        // do nothing
195    }
196
197    #[inline(always)]
198    fn record_hasher_build_merkle_root(
199        &mut self,
200        _node: Word,
201        _path: Option<&MerklePath>,
202        _index: Felt,
203        _output_root: Word,
204    ) {
205        // do nothing
206    }
207
208    #[inline(always)]
209    fn record_hasher_update_merkle_root(
210        &mut self,
211        _old_node: Word,
212        _new_node: Word,
213        _path: Option<&MerklePath>,
214        _index: Felt,
215        _old_root: Word,
216        _new_root: Word,
217    ) {
218        // do nothing
219    }
220
221    #[inline(always)]
222    fn record_memory_read_element(
223        &mut self,
224        _element: Felt,
225        _addr: Felt,
226        _ctx: ContextId,
227        _clk: RowIndex,
228    ) {
229        // do nothing
230    }
231
232    #[inline(always)]
233    fn record_memory_read_word(
234        &mut self,
235        _word: Word,
236        _addr: Felt,
237        _ctx: ContextId,
238        _clk: RowIndex,
239    ) {
240        // do nothing
241    }
242
243    #[inline(always)]
244    fn record_memory_write_element(
245        &mut self,
246        _element: Felt,
247        _addr: Felt,
248        _ctx: ContextId,
249        _clk: RowIndex,
250    ) {
251        // do nothing
252    }
253
254    #[inline(always)]
255    fn record_memory_write_word(
256        &mut self,
257        _word: Word,
258        _addr: Felt,
259        _ctx: ContextId,
260        _clk: RowIndex,
261    ) {
262        // do nothing
263    }
264
265    #[inline(always)]
266    fn record_advice_pop_stack(&mut self, _value: Felt) {
267        // do nothing
268    }
269
270    #[inline(always)]
271    fn record_advice_pop_stack_word(&mut self, _word: Word) {
272        // do nothing
273    }
274
275    #[inline(always)]
276    fn record_advice_pop_stack_dword(&mut self, _words: [Word; 2]) {
277        // do nothing
278    }
279
280    #[inline(always)]
281    fn record_u32and(&mut self, _a: Felt, _b: Felt) {
282        // do nothing
283    }
284
285    #[inline(always)]
286    fn record_u32xor(&mut self, _a: Felt, _b: Felt) {
287        // do nothing
288    }
289
290    #[inline(always)]
291    fn record_u32_range_checks(&mut self, _clk: RowIndex, _u32_lo: Felt, _u32_hi: Felt) {
292        // do nothing
293    }
294
295    #[inline(always)]
296    fn record_kernel_proc_access(&mut self, _proc_hash: Word) {
297        // do nothing
298    }
299
300    #[inline(always)]
301    fn record_circuit_evaluation(&mut self, _clk: RowIndex, _circuit_eval: CircuitEvaluation) {
302        // do nothing
303    }
304
305    #[inline(always)]
306    fn increment_clk(&mut self) {
307        // do nothing
308    }
309
310    #[inline(always)]
311    fn increment_stack_size(&mut self, _processor: &FastProcessor) {
312        // do nothing
313    }
314
315    #[inline(always)]
316    fn decrement_stack_size(&mut self) {
317        // do nothing
318    }
319
320    #[inline(always)]
321    fn start_context(&mut self) {
322        // do nothing
323    }
324
325    #[inline(always)]
326    fn restore_context(&mut self) {
327        // do nothing
328    }
329}