use ligerito::pcvm::{
memory::ReadOnlyMemory,
trace::{execute_and_trace_with_memory, Instruction, Opcode, Program},
};
#[test]
fn test_simple_load() {
let mut memory = ReadOnlyMemory::with_size(0x2000);
memory.write(0x1000, 42).unwrap();
let program = vec![
Instruction::new_imm(1, 0x1000), Instruction::new_load(0, 1, 0), Instruction::halt(),
];
let initial_regs = [0u32; 13];
let trace = execute_and_trace_with_memory(&program, initial_regs, Some(&memory));
assert!(trace.validate().is_ok());
let final_state = trace.final_state().unwrap();
assert_eq!(final_state[0], 42, "a0 should contain loaded value");
}
#[test]
fn test_load_with_offset() {
let mut memory = ReadOnlyMemory::with_size(0x2000);
memory.write(0x1000, 10).unwrap();
memory.write(0x1004, 20).unwrap();
memory.write(0x1008, 30).unwrap();
let program = vec![
Instruction::new_imm(1, 0x1000), Instruction::new_load(0, 1, 0), Instruction::new_load(2, 1, 4), Instruction::new_load(3, 1, 8), Instruction::halt(),
];
let initial_regs = [0u32; 13];
let trace = execute_and_trace_with_memory(&program, initial_regs, Some(&memory));
assert!(trace.validate().is_ok());
let final_state = trace.final_state().unwrap();
assert_eq!(final_state[0], 10);
assert_eq!(final_state[2], 20);
assert_eq!(final_state[3], 30);
}
#[test]
fn test_load_and_compute() {
let mut memory = ReadOnlyMemory::with_size(0x2000);
memory.write(0x1000, 15).unwrap();
memory.write(0x1004, 25).unwrap();
let program = vec![
Instruction::new_imm(1, 0x1000), Instruction::new_load(0, 1, 0), Instruction::new_load(2, 1, 4), Instruction::new_rrr(Opcode::ADD, 3, 0, 2), Instruction::halt(),
];
let initial_regs = [0u32; 13];
let trace = execute_and_trace_with_memory(&program, initial_regs, Some(&memory));
assert!(trace.validate().is_ok());
let final_state = trace.final_state().unwrap();
assert_eq!(final_state[3], 40);
}
#[test]
fn test_memory_hash_integrity() {
let mut mem1 = ReadOnlyMemory::with_size(100);
mem1.write(50, 123).unwrap();
let mut mem2 = ReadOnlyMemory::with_size(100);
mem2.write(50, 456).unwrap();
assert_ne!(mem1.hash, mem2.hash);
let mut mem3 = ReadOnlyMemory::with_size(100);
mem3.write(50, 123).unwrap();
assert_eq!(mem1.hash, mem3.hash);
}
#[test]
fn test_backward_compatibility() {
let program = vec![
Instruction::new_imm(0, 10),
Instruction::new_imm(1, 20),
Instruction::new_rrr(Opcode::ADD, 2, 0, 1),
Instruction::halt(),
];
let initial_regs = [0u32; 13];
let trace = execute_and_trace_with_memory(&program, initial_regs, None);
assert!(trace.validate().is_ok());
let final_state = trace.final_state().unwrap();
assert_eq!(final_state[2], 30);
}
#[test]
fn test_load_out_of_bounds() {
let memory = ReadOnlyMemory::with_size(100);
let program = vec![
Instruction::new_imm(1, 1000), Instruction::new_load(0, 1, 0), Instruction::halt(),
];
let initial_regs = [0u32; 13];
let trace = execute_and_trace_with_memory(&program, initial_regs, Some(&memory));
assert!(trace.validate().is_ok());
let final_state = trace.final_state().unwrap();
assert_eq!(final_state[0], 0, "Out of bounds read should return 0");
}