sp1_core_machine/memory/consistency/
trace.rs1use slop_algebra::PrimeField32;
2use sp1_core_executor::events::{ByteRecord, MemoryRecordEnum, PageProtRecord};
3
4use super::{
5 MemoryAccessCols, MemoryAccessColsU8, MemoryAccessTimestamp, PageProtAccessCols,
6 RegisterAccessCols, RegisterAccessTimestamp,
7};
8
9impl<F: PrimeField32> MemoryAccessCols<F> {
10 pub fn populate(&mut self, record: MemoryRecordEnum, output: &mut impl ByteRecord) {
11 let prev_record = record.previous_record();
12 let current_record = record.current_record();
13 self.prev_value = prev_record.value.into();
14 self.access_timestamp.populate_timestamp(
15 prev_record.timestamp,
16 current_record.timestamp,
17 output,
18 );
19 }
20}
21
22impl<F: PrimeField32> RegisterAccessCols<F> {
23 pub fn populate(&mut self, record: MemoryRecordEnum, output: &mut impl ByteRecord) {
24 let prev_record = record.previous_record();
25 let current_record = record.current_record();
26 self.prev_value = prev_record.value.into();
27 self.access_timestamp.populate_timestamp(
28 prev_record.timestamp,
29 current_record.timestamp,
30 output,
31 );
32 }
33}
34
35impl<F: PrimeField32> MemoryAccessColsU8<F> {
36 pub fn populate(&mut self, record: MemoryRecordEnum, output: &mut impl ByteRecord) {
37 let prev_record = record.previous_record();
38 let current_record = record.current_record();
39 self.memory_access.prev_value = prev_record.value.into();
40 self.prev_value_u8.populate_u16_to_u8_safe(output, prev_record.value);
41 self.memory_access.access_timestamp.populate_timestamp(
42 prev_record.timestamp,
43 current_record.timestamp,
44 output,
45 );
46 }
47}
48
49impl<F: PrimeField32> PageProtAccessCols<F> {
50 pub fn populate(
51 &mut self,
52 prev_page_prot: &PageProtRecord,
53 current_timestamp: u64,
54 output: &mut impl ByteRecord,
55 ) {
56 self.prev_prot_bitmap = F::from_canonical_u8(prev_page_prot.page_prot);
57 self.access_timestamp.populate_timestamp(
58 prev_page_prot.timestamp,
59 current_timestamp,
60 output,
61 );
62 }
63}
64
65impl<F: PrimeField32> MemoryAccessTimestamp<F> {
66 pub fn populate_timestamp(
67 &mut self,
68 prev_timestamp: u64,
69 current_timestamp: u64,
70 output: &mut impl ByteRecord,
71 ) {
72 assert!(
73 prev_timestamp < current_timestamp,
74 "prev_timestamp: {prev_timestamp}, current_timestamp: {current_timestamp}"
75 );
76 let prev_high = (prev_timestamp >> 24) as u32;
77 let prev_low = (prev_timestamp & 0xFFFFFF) as u32;
78 let current_high = (current_timestamp >> 24) as u32;
79 let current_low = (current_timestamp & 0xFFFFFF) as u32;
80 self.prev_high = F::from_canonical_u32(prev_high);
81 self.prev_low = F::from_canonical_u32(prev_low);
82
83 let use_low_comparison = prev_high == current_high;
85 self.compare_low = F::from_bool(use_low_comparison);
86 let prev_time_value = if use_low_comparison { prev_low } else { prev_high };
87 let current_time_value = if use_low_comparison { current_low } else { current_high };
88
89 let diff_minus_one = current_time_value - prev_time_value - 1;
90 let diff_low_limb = (diff_minus_one & 0xFFFF) as u16;
91 self.diff_low_limb = F::from_canonical_u16(diff_low_limb);
92 let diff_high_limb = (diff_minus_one >> 16) as u8;
93 self.diff_high_limb = F::from_canonical_u8(diff_high_limb);
94
95 output.add_bit_range_check(diff_low_limb, 16);
97 output.add_u8_range_check(diff_high_limb, 0);
98 }
99}
100
101impl<F: PrimeField32> RegisterAccessTimestamp<F> {
102 pub fn populate_timestamp(
103 &mut self,
104 prev_timestamp: u64,
105 current_timestamp: u64,
106 output: &mut impl ByteRecord,
107 ) {
108 let prev_high = (prev_timestamp >> 24) as u32;
109 let prev_low = (prev_timestamp & 0xFFFFFF) as u32;
110 let current_high = (current_timestamp >> 24) as u32;
111 let current_low = (current_timestamp & 0xFFFFFF) as u32;
112
113 let old_timestamp = if prev_high == current_high { prev_low } else { 0 };
114 self.prev_low = F::from_canonical_u32(old_timestamp);
115 let diff_minus_one = current_low - old_timestamp - 1;
116 let diff_low_limb = (diff_minus_one & 0xFFFF) as u16;
117 self.diff_low_limb = F::from_canonical_u16(diff_low_limb);
118 let diff_high_limb = (diff_minus_one >> 16) as u8;
119
120 output.add_bit_range_check(diff_low_limb, 16);
122 output.add_u8_range_check(diff_high_limb, 0);
123 }
124}