use super::{
build_trace_from_ops, rand_array, ExecutionTrace, Felt, FieldElement, Operation, Trace, Word,
AUX_TRACE_RAND_ELEMENTS, CHIPLETS_AUX_TRACE_OFFSET, NUM_RAND_ROWS, ONE, ZERO,
};
use miden_air::trace::chiplets::{
memory::{MEMORY_READ_LABEL, MEMORY_WRITE, MEMORY_WRITE_LABEL, NUM_ELEMENTS},
MEMORY_ADDR_COL_IDX, MEMORY_CLK_COL_IDX, MEMORY_CTX_COL_IDX, MEMORY_SELECTORS_COL_IDX,
MEMORY_V_COL_RANGE,
};
#[test]
#[allow(clippy::needless_range_loop)]
fn b_chip_trace_mem() {
let stack = [1, 2, 3, 4, 0];
let word = [ONE, Felt::new(2), Felt::new(3), Felt::new(4)];
let operations = vec![
Operation::MStoreW, Operation::Drop, Operation::Drop,
Operation::Drop,
Operation::Drop,
Operation::MLoad, Operation::MovDn5, Operation::MLoadW, Operation::Push(ONE), Operation::Push(ONE), Operation::MStore, Operation::Drop, Operation::MStream, ];
let mut trace = build_trace_from_ops(operations, &stack);
let rand_elements = rand_array::<Felt, AUX_TRACE_RAND_ELEMENTS>();
let aux_columns = trace.build_aux_segment(&[], &rand_elements).unwrap();
let b_chip = aux_columns.get_column(CHIPLETS_AUX_TRACE_OFFSET);
assert_eq!(trace.length(), b_chip.len());
assert_eq!(ONE, b_chip[0]);
assert_eq!(ONE, b_chip[1]);
let value = build_expected_memory(&rand_elements, MEMORY_WRITE_LABEL, ZERO, ZERO, ONE, word);
let mut expected = value.inv();
assert_eq!(expected, b_chip[2]);
for row in 3..7 {
assert_eq!(expected, b_chip[row]);
}
let value =
build_expected_memory(&rand_elements, MEMORY_READ_LABEL, ZERO, ZERO, Felt::new(6), word);
expected *= value.inv();
assert_eq!(expected, b_chip[7]);
assert_ne!(expected, b_chip[8]);
let span_result = b_chip[8] * b_chip[7].inv();
expected = b_chip[8];
let value =
build_expected_memory(&rand_elements, MEMORY_READ_LABEL, ZERO, ZERO, Felt::new(8), word);
expected *= value.inv();
expected *= build_expected_memory_from_trace(&trace, &rand_elements, 8);
assert_eq!(expected, b_chip[9]);
expected *= build_expected_memory_from_trace(&trace, &rand_elements, 9);
assert_eq!(expected, b_chip[10]);
expected *= build_expected_memory_from_trace(&trace, &rand_elements, 10);
assert_eq!(expected, b_chip[11]);
let value = build_expected_memory(
&rand_elements,
MEMORY_WRITE_LABEL,
ZERO,
ONE,
Felt::new(11),
[ONE, ZERO, ZERO, ZERO],
);
expected *= value.inv();
expected *= build_expected_memory_from_trace(&trace, &rand_elements, 11);
assert_eq!(expected, b_chip[12]);
expected *= build_expected_memory_from_trace(&trace, &rand_elements, 12);
assert_eq!(expected, b_chip[13]);
let value1 =
build_expected_memory(&rand_elements, MEMORY_READ_LABEL, ZERO, ZERO, Felt::new(13), word);
let value2 = build_expected_memory(
&rand_elements,
MEMORY_READ_LABEL,
ZERO,
ONE,
Felt::new(13),
[ONE, ZERO, ZERO, ZERO],
);
expected *= (value1 * value2).inv();
expected *= build_expected_memory_from_trace(&trace, &rand_elements, 13);
assert_eq!(expected, b_chip[14]);
assert_ne!(expected, b_chip[15]);
expected *= span_result.inv();
assert_eq!(expected, b_chip[15]);
for row in 15..trace.length() - NUM_RAND_ROWS {
assert_eq!(ONE, b_chip[row]);
}
}
fn build_expected_memory(
alphas: &[Felt],
op_label: u8,
ctx: Felt,
addr: Felt,
clk: Felt,
word: Word,
) -> Felt {
let mut word_value = ZERO;
for i in 0..NUM_ELEMENTS {
word_value += alphas[i + 5] * word[i];
}
alphas[0]
+ alphas[1] * Felt::from(op_label)
+ alphas[2] * ctx
+ alphas[3] * addr
+ alphas[4] * clk
+ word_value
}
fn build_expected_memory_from_trace(trace: &ExecutionTrace, alphas: &[Felt], row: usize) -> Felt {
let s0 = trace.main_trace.get_column(MEMORY_SELECTORS_COL_IDX)[row];
let s1 = trace.main_trace.get_column(MEMORY_SELECTORS_COL_IDX + 1)[row];
let op_label = if s0 == MEMORY_WRITE[0] {
debug_assert!(s1 == ZERO);
MEMORY_WRITE_LABEL
} else {
MEMORY_READ_LABEL
};
let ctx = trace.main_trace.get_column(MEMORY_CTX_COL_IDX)[row];
let addr = trace.main_trace.get_column(MEMORY_ADDR_COL_IDX)[row];
let clk = trace.main_trace.get_column(MEMORY_CLK_COL_IDX)[row];
let mut word = [ZERO; NUM_ELEMENTS];
for (i, element) in word.iter_mut().enumerate() {
*element = trace.main_trace.get_column(MEMORY_V_COL_RANGE.start + i)[row];
}
build_expected_memory(alphas, op_label, ctx, addr, clk, word)
}