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}