use alloc::vec::Vec;
use miden_air::{logup::BitwiseMsg, trace::chiplets::BITWISE_SELECTOR_COL_IDX};
use miden_core::{
Felt,
operations::{Operation, opcodes},
};
use super::super::{
build_trace_from_ops,
lookup_harness::{Expectations, InteractionLog},
};
use crate::RowIndex;
const BITWISE_CYCLE_LEN: usize = 8;
#[test]
fn bitwise_chiplet_bus_emits_per_request_row() {
let a1: u32 = 0x1111_2222;
let b1: u32 = 0x3333_4444;
let a2: u32 = 0x5555_6666;
let b2: u32 = 0x7777_8888;
let a3: u32 = 0xdead_beef;
let b3: u32 = 0x1234_5678;
let ops = vec![
Operation::Push(Felt::from_u32(a1)),
Operation::Push(Felt::from_u32(b1)),
Operation::U32and,
Operation::Drop,
Operation::Push(Felt::from_u32(a2)),
Operation::Push(Felt::from_u32(b2)),
Operation::U32and,
Operation::Drop,
Operation::Push(Felt::from_u32(a3)),
Operation::Push(Felt::from_u32(b3)),
Operation::U32xor,
Operation::Drop,
];
let trace = build_trace_from_ops(ops, &[]);
let log = InteractionLog::new(&trace);
let main = trace.main_trace();
let mut exp = Expectations::new(&log);
let and_expected = [(a1, b1, a1 & b1), (a2, b2, a2 & b2)];
let xor_expected = [(a3, b3, a3 ^ b3)];
let mut and_rows: Vec<RowIndex> = Vec::new();
let mut xor_rows: Vec<RowIndex> = Vec::new();
for row in 0..main.num_rows() {
let idx = RowIndex::from(row);
let op = main.get_op_code(idx).as_canonical_u64();
if op == opcodes::U32AND as u64 {
and_rows.push(idx);
} else if op == opcodes::U32XOR as u64 {
xor_rows.push(idx);
}
}
assert_eq!(
and_rows.len(),
and_expected.len(),
"request cardinality guardrail: expected {} U32AND rows, found {}",
and_expected.len(),
and_rows.len(),
);
assert_eq!(
xor_rows.len(),
xor_expected.len(),
"request cardinality guardrail: expected {} U32XOR rows, found {}",
xor_expected.len(),
xor_rows.len(),
);
for (&row, &(a, b, c)) in and_rows.iter().zip(and_expected.iter()) {
let msg = BitwiseMsg::and(Felt::from_u32(b), Felt::from_u32(a), Felt::from_u32(c));
exp.remove(usize::from(row), &msg);
}
for (&row, &(a, b, c)) in xor_rows.iter().zip(xor_expected.iter()) {
let msg = BitwiseMsg::xor(Felt::from_u32(b), Felt::from_u32(a), Felt::from_u32(c));
exp.remove(usize::from(row), &msg);
}
let mut response_rows_seen = 0usize;
for row in 0..main.num_rows() {
let idx = RowIndex::from(row);
if !main.is_bitwise_row(idx) {
continue;
}
if row % BITWISE_CYCLE_LEN != BITWISE_CYCLE_LEN - 1 {
continue;
}
response_rows_seen += 1;
let op = main.get(idx, BITWISE_SELECTOR_COL_IDX);
let a = main.chiplet_bitwise_a(idx);
let b = main.chiplet_bitwise_b(idx);
let z = main.chiplet_bitwise_z(idx);
exp.add(row, &BitwiseMsg { op, a, b, result: z });
}
let expected_responses = and_expected.len() + xor_expected.len();
assert_eq!(
response_rows_seen, expected_responses,
"response cardinality guardrail: expected {expected_responses} cycle-end bitwise rows, \
found {response_rows_seen}",
);
log.assert_contains(&exp);
}