sp1_core_executor/minimal/
postprocess.rs1use hashbrown::HashSet;
2
3use crate::{
4 events::{MemoryInitializeFinalizeEvent, MemoryRecord},
5 ExecutionRecord, MinimalExecutor,
6};
7
8impl MinimalExecutor {
9 #[tracing::instrument(name = "emit globals", skip_all)]
12 pub fn emit_globals(
13 &self,
14 record: &mut ExecutionRecord,
15 final_registers: [MemoryRecord; 32],
16 mut touched_addresses: HashSet<u64>,
17 ) {
18 touched_addresses.extend(self.program().memory_image.keys().copied());
20
21 record.global_memory_initialize_events.extend(
22 final_registers
23 .iter()
24 .enumerate()
25 .filter(|(_, e)| e.timestamp != 0)
26 .map(|(i, _)| MemoryInitializeFinalizeEvent::initialize(i as u64, 0)),
27 );
28
29 record.global_memory_finalize_events.extend(
30 final_registers.iter().enumerate().filter(|(_, e)| e.timestamp != 0).map(
31 |(i, entry)| {
32 MemoryInitializeFinalizeEvent::finalize(i as u64, entry.value, entry.timestamp)
33 },
34 ),
35 );
36
37 let hint_init_events: Vec<MemoryInitializeFinalizeEvent> = self
38 .hints()
39 .iter()
40 .flat_map(|(addr, value)| chunked_memory_init_events(*addr, value))
41 .collect::<Vec<_>>();
42 let hint_addrs = hint_init_events.iter().map(|event| event.addr).collect::<HashSet<_>>();
43
44 record.global_memory_initialize_events.extend(hint_init_events);
46
47 let memory_init_events = touched_addresses
51 .iter()
52 .filter(|addr| !self.program().memory_image.contains_key(*addr))
53 .filter(|addr| !hint_addrs.contains(*addr))
54 .map(|addr| MemoryInitializeFinalizeEvent::initialize(*addr, 0));
55 record.global_memory_initialize_events.extend(memory_init_events);
56
57 touched_addresses.extend(hint_addrs);
59
60 for addr in &touched_addresses {
62 let entry = self.get_memory_value(*addr);
63
64 record.global_memory_finalize_events.push(MemoryInitializeFinalizeEvent::finalize(
65 *addr,
66 entry.value,
67 entry.clk,
68 ));
69 }
70 }
71
72 #[must_use]
74 pub fn get_hint_event_addrs(&self) -> HashSet<u64> {
75 let events = self
76 .hints()
77 .iter()
78 .flat_map(|(addr, value)| chunked_memory_init_events(*addr, value))
79 .collect::<Vec<_>>();
80 let hint_event_addrs = events.iter().map(|event| event.addr).collect::<HashSet<_>>();
81
82 hint_event_addrs
83 }
84}
85
86#[must_use]
93pub fn chunked_memory_init_events(start: u64, bytes: &[u8]) -> Vec<MemoryInitializeFinalizeEvent> {
94 let chunks = bytes.chunks_exact(8);
95 let num_chunks = chunks.len();
96 let last = chunks.remainder();
97
98 let mut output = Vec::with_capacity(num_chunks + 1);
99
100 for (i, chunk) in chunks.enumerate() {
101 let addr = start + i as u64 * 8;
102 let value = u64::from_le_bytes(chunk.try_into().unwrap());
103 output.push(MemoryInitializeFinalizeEvent::initialize(addr, value));
104 }
105
106 if !last.is_empty() {
107 let addr = start + num_chunks as u64 * 8;
108 let buf = {
109 let mut buf = [0u8; 8];
110 buf[..last.len()].copy_from_slice(last);
111 buf
112 };
113
114 let value = u64::from_le_bytes(buf);
115 output.push(MemoryInitializeFinalizeEvent::initialize(addr, value));
116 }
117
118 output
119}