diff --git a/ceno_emul/src/tracer.rs b/ceno_emul/src/tracer.rs index 54dfafe78..8aa55cf79 100644 --- a/ceno_emul/src/tracer.rs +++ b/ceno_emul/src/tracer.rs @@ -286,6 +286,10 @@ impl StepRecord { pub fn is_busy_loop(&self) -> bool { self.pc.before == self.pc.after } + + pub fn syscall(&self) -> Option<&SyscallWitness> { + self.syscall.as_ref() + } } #[derive(Debug)] diff --git a/ceno_emul/tests/test_elf.rs b/ceno_emul/tests/test_elf.rs index 7f5c328d6..afbd67a12 100644 --- a/ceno_emul/tests/test_elf.rs +++ b/ceno_emul/tests/test_elf.rs @@ -78,18 +78,43 @@ fn test_ceno_rt_io() -> Result<()> { fn test_ceno_rt_keccak() -> Result<()> { let program_elf = ceno_examples::ceno_rt_keccak; let mut state = VMState::new_from_elf(unsafe_platform(), program_elf)?; - let _steps = run(&mut state)?; + let steps = run(&mut state)?; // Expect the program to have written successive states between Keccak permutations. const ITERATIONS: usize = 3; let keccak_outs = sample_keccak_f(ITERATIONS); let all_messages = read_all_messages(&state); - for (got, expect) in izip!(&all_messages, keccak_outs) { + assert_eq!(all_messages.len(), ITERATIONS); + for (got, expect) in izip!(&all_messages, &keccak_outs) { let got = got .chunks_exact(8) .map(|chunk| u64::from_le_bytes(chunk.try_into().unwrap())) .collect_vec(); + assert_eq!(&got, expect); + } + + // Find the syscall records. + let syscalls = steps.iter().filter_map(|step| step.syscall()).collect_vec(); + assert_eq!(syscalls.len(), ITERATIONS); + + // Check the syscall effects. + for (witness, expect) in izip!(syscalls, keccak_outs) { + assert_eq!(witness.mem_writes.len(), expect.len() * 2); + + let got = witness + .mem_writes + .chunks_exact(2) + .map(|write_ops| { + assert_eq!( + write_ops[1].addr.baddr(), + write_ops[0].addr.baddr() + WORD_SIZE as u32 + ); + let lo = write_ops[0].value.after as u64; + let hi = write_ops[1].value.after as u64; + lo | (hi << 32) + }) + .collect_vec(); assert_eq!(got, expect); } @@ -103,8 +128,7 @@ fn unsafe_platform() -> Platform { } fn sample_keccak_f(count: usize) -> Vec> { - let input = [0_u64; 25]; - let mut state = input.clone(); + let mut state = [0_u64; 25]; (0..count) .map(|_| { diff --git a/examples/examples/ceno_rt_keccak.rs b/examples/examples/ceno_rt_keccak.rs index 07fb7b9ca..cd68d17db 100644 --- a/examples/examples/ceno_rt_keccak.rs +++ b/examples/examples/ceno_rt_keccak.rs @@ -6,7 +6,7 @@ #![no_std] extern crate ceno_rt; use ceno_rt::{info_out, syscall_keccak_permute}; -use core::{ptr::read_volatile, slice}; +use core::slice; const ITERATIONS: usize = 3; @@ -22,7 +22,7 @@ fn main() { fn log_state(state: &[u64; 25]) { let out = unsafe { - slice::from_raw_parts_mut(state.as_ptr() as *mut u8, state.len() * size_of::()) + slice::from_raw_parts(state.as_ptr() as *const u8, state.len() * size_of::()) }; info_out().write_frame(out); }