1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
mod air;
mod columns;

use p3_field::PrimeField32;

use crate::air::Block;
pub use air::compute_addr_diff;
pub use columns::*;

#[allow(clippy::manual_non_exhaustive)]
#[derive(Debug, Clone, Copy)]
pub struct MemoryRecord<F> {
    pub addr: F,
    pub value: Block<F>,
    pub prev_value: Block<F>,
    pub timestamp: F,
    pub prev_timestamp: F,
    pub diff_16bit_limb: F,
    pub diff_12bit_limb: F,
    _private: (),
}

/// Computes the difference between the current memory access timestamp and the previous one's.
///
/// This function will compute the difference minus one and then decompose the result into a 16 bit
/// limb and 12 bit limb.  The minus one is needed since a difference of zero is not valid.  Also,
/// we assume that the clk/timestamp value will always be less than 2^28.
fn compute_diff<F: PrimeField32>(timestamp: F, prev_timestamp: F) -> (F, F) {
    let diff_minus_one = timestamp.as_canonical_u32() - prev_timestamp.as_canonical_u32() - 1;
    let diff_16bit_limb = diff_minus_one & 0xffff;
    let diff_12bit_limb = (diff_minus_one >> 16) & 0xfff;
    (F::from_canonical_u32(diff_16bit_limb), F::from_canonical_u32(diff_12bit_limb))
}

impl<F: Clone + PrimeField32> MemoryRecord<F> {
    pub fn new_write(
        addr: F,
        value: Block<F>,
        timestamp: F,
        prev_value: Block<F>,
        prev_timestamp: F,
    ) -> Self {
        assert!(timestamp >= prev_timestamp);
        let (diff_16bit_limb, diff_12bit_limb) = compute_diff(timestamp, prev_timestamp);
        Self {
            addr,
            value,
            prev_value,
            timestamp,
            prev_timestamp,
            diff_16bit_limb,
            diff_12bit_limb,
            _private: (),
        }
    }

    pub fn new_read(addr: F, value: Block<F>, timestamp: F, prev_timestamp: F) -> Self {
        assert!(timestamp >= prev_timestamp);
        let (diff_16bit_limb, diff_12bit_limb) = compute_diff(timestamp, prev_timestamp);
        Self {
            addr,
            value,
            prev_value: value,
            timestamp,
            prev_timestamp,
            diff_16bit_limb,
            diff_12bit_limb,
            _private: (),
        }
    }
}

impl<T: PrimeField32> MemoryReadWriteCols<T> {
    pub fn populate(&mut self, record: &MemoryRecord<T>) {
        self.prev_value = record.prev_value;
        self.access.populate(record.value, record);
    }
}

impl<T: PrimeField32> MemoryReadCols<T> {
    pub fn populate(&mut self, record: &MemoryRecord<T>) {
        self.access.populate(record.value, record);
    }
}

impl<T: PrimeField32> MemoryReadWriteSingleCols<T> {
    pub fn populate(&mut self, record: &MemoryRecord<T>) {
        self.prev_value = record.prev_value[0];
        self.access.populate(record.value[0], record);
    }
}

impl<T: PrimeField32> MemoryReadSingleCols<T> {
    pub fn populate(&mut self, record: &MemoryRecord<T>) {
        self.access.populate(record.value[0], record);
    }
}

impl<F: PrimeField32, TValue> MemoryAccessCols<F, TValue> {
    /// Populate the memory access columns.
    pub fn populate(&mut self, value: TValue, record: &MemoryRecord<F>) {
        self.value = value;
        self.prev_timestamp = record.prev_timestamp;
        self.diff_16bit_limb = record.diff_16bit_limb;
        self.diff_12bit_limb = record.diff_12bit_limb;
    }
}

#[derive(Default)]
pub struct MemoryGlobalChip {
    pub fixed_log2_rows: Option<usize>,
}