sp1_core_machine/memory/consistency/
trace.rs

1use p3_field::PrimeField32;
2use sp1_core_executor::events::{
3    ByteRecord, MemoryReadRecord, MemoryRecord, MemoryRecordEnum, MemoryWriteRecord,
4};
5
6use super::{MemoryAccessCols, MemoryReadCols, MemoryReadWriteCols, MemoryWriteCols};
7
8impl<F: PrimeField32> MemoryWriteCols<F> {
9    pub fn populate(&mut self, record: MemoryWriteRecord, output: &mut impl ByteRecord) {
10        let current_record =
11            MemoryRecord { value: record.value, shard: record.shard, timestamp: record.timestamp };
12        let prev_record = MemoryRecord {
13            value: record.prev_value,
14            shard: record.prev_shard,
15            timestamp: record.prev_timestamp,
16        };
17        self.prev_value = prev_record.value.into();
18        self.access.populate_access(current_record, prev_record, output);
19    }
20}
21
22impl<F: PrimeField32> MemoryReadCols<F> {
23    pub fn populate(&mut self, record: MemoryReadRecord, output: &mut impl ByteRecord) {
24        let current_record =
25            MemoryRecord { value: record.value, shard: record.shard, timestamp: record.timestamp };
26        let prev_record = MemoryRecord {
27            value: record.value,
28            shard: record.prev_shard,
29            timestamp: record.prev_timestamp,
30        };
31        self.access.populate_access(current_record, prev_record, output);
32    }
33}
34
35impl<F: PrimeField32> MemoryReadWriteCols<F> {
36    pub fn populate(&mut self, record: MemoryRecordEnum, output: &mut impl ByteRecord) {
37        match record {
38            MemoryRecordEnum::Read(read_record) => self.populate_read(read_record, output),
39            MemoryRecordEnum::Write(write_record) => self.populate_write(write_record, output),
40        }
41    }
42
43    pub fn populate_write(&mut self, record: MemoryWriteRecord, output: &mut impl ByteRecord) {
44        let current_record =
45            MemoryRecord { value: record.value, shard: record.shard, timestamp: record.timestamp };
46        let prev_record = MemoryRecord {
47            value: record.prev_value,
48            shard: record.prev_shard,
49            timestamp: record.prev_timestamp,
50        };
51        self.prev_value = prev_record.value.into();
52        self.access.populate_access(current_record, prev_record, output);
53    }
54
55    pub fn populate_read(&mut self, record: MemoryReadRecord, output: &mut impl ByteRecord) {
56        let current_record =
57            MemoryRecord { value: record.value, shard: record.shard, timestamp: record.timestamp };
58        let prev_record = MemoryRecord {
59            value: record.value,
60            shard: record.prev_shard,
61            timestamp: record.prev_timestamp,
62        };
63        self.prev_value = prev_record.value.into();
64        self.access.populate_access(current_record, prev_record, output);
65    }
66}
67
68impl<F: PrimeField32> MemoryAccessCols<F> {
69    pub(crate) fn populate_access(
70        &mut self,
71        current_record: MemoryRecord,
72        prev_record: MemoryRecord,
73        output: &mut impl ByteRecord,
74    ) {
75        self.value = current_record.value.into();
76
77        self.prev_shard = F::from_canonical_u32(prev_record.shard);
78        self.prev_clk = F::from_canonical_u32(prev_record.timestamp);
79
80        // Fill columns used for verifying current memory access time value is greater than
81        // previous's.
82        let use_clk_comparison = prev_record.shard == current_record.shard;
83        self.compare_clk = F::from_bool(use_clk_comparison);
84        let prev_time_value =
85            if use_clk_comparison { prev_record.timestamp } else { prev_record.shard };
86        let current_time_value =
87            if use_clk_comparison { current_record.timestamp } else { current_record.shard };
88
89        let diff_minus_one = current_time_value - prev_time_value - 1;
90        let diff_16bit_limb = (diff_minus_one & 0xffff) as u16;
91        self.diff_16bit_limb = F::from_canonical_u16(diff_16bit_limb);
92        let diff_8bit_limb = (diff_minus_one >> 16) & 0xff;
93        self.diff_8bit_limb = F::from_canonical_u32(diff_8bit_limb);
94
95        // Add a byte table lookup with the 16Range op.
96        output.add_u16_range_check(diff_16bit_limb);
97
98        // Add a byte table lookup with the U8Range op.
99        output.add_u8_range_check(0, diff_8bit_limb as u8);
100    }
101}