From 3074e7114f76333e1a611c31a949a1f9e5df6d8f Mon Sep 17 00:00:00 2001 From: Danny Willems Date: Thu, 30 Nov 2023 22:14:06 +0100 Subject: [PATCH 1/2] Implementing jump --- optimism/src/mips/interpreter.rs | 28 +++++++++++++++++++--- optimism/src/mips/witness.rs | 41 ++++++++++++++++++++++++-------- 2 files changed, 56 insertions(+), 13 deletions(-) diff --git a/optimism/src/mips/interpreter.rs b/optimism/src/mips/interpreter.rs index 2180c5f711..63f53db97c 100644 --- a/optimism/src/mips/interpreter.rs +++ b/optimism/src/mips/interpreter.rs @@ -133,7 +133,16 @@ pub enum ITypeInstruction { } pub trait InterpreterEnv { - type Variable: Clone + std::ops::Add; + type Variable: Clone + + std::ops::Add + + std::ops::Mul + + std::ops::Shl + + std::ops::BitAnd + + std::fmt::Display; + + fn set_instruction_pointer(&mut self, ip: Self::Variable); + + fn get_instruction_part(&self, part: InstructionPart) -> Self::Variable; fn constant(x: u32) -> Self::Variable; @@ -198,11 +207,24 @@ pub fn interpret_rtype(env: &mut Env, instr: RTypeInstructi pub fn interpret_jtype(env: &mut Env, instr: JTypeInstruction) { match instr { - JTypeInstruction::Jump => (), + JTypeInstruction::Jump => { + // > The address stored in a j instruction is 26 bits of the address + // > associated with the specified label. The 26 bits are achieved by + // > dropping the high-order 4 bits of the address and the low-order 2 + // > bits (which would always be 00, since addresses are always + // > divisible by 4). + // Source: https://max.cs.kzoo.edu/cs230/Resources/MIPS/MachineXL/InstructionFormats.html + let addr = (env.get_instruction_part(InstructionPart::RS) << 21) + + (env.get_instruction_part(InstructionPart::RT) << 16) + + (env.get_instruction_part(InstructionPart::RD) << 11) + + (env.get_instruction_part(InstructionPart::Shamt) << 6) + + (env.get_instruction_part(InstructionPart::Funct)); + env.set_instruction_pointer(addr * 4); + } JTypeInstruction::JumpAndLink => (), }; // TODO: Don't halt. - env.set_halted(Env::constant(1)); + // env.set_halted(Env::constant(1)); } pub fn interpret_itype(env: &mut Env, instr: ITypeInstruction) { diff --git a/optimism/src/mips/witness.rs b/optimism/src/mips/witness.rs index db2d6cacf5..57444bc8a0 100644 --- a/optimism/src/mips/witness.rs +++ b/optimism/src/mips/witness.rs @@ -5,7 +5,7 @@ use crate::{ }, mips::{ interpreter::{ - self, ITypeInstruction, Instruction, InstructionParts, InterpreterEnv, + self, ITypeInstruction, Instruction, InstructionPart, InstructionParts, InterpreterEnv, JTypeInstruction, RTypeInstruction, }, registers::Registers, @@ -13,7 +13,7 @@ use crate::{ preimage_oracle::PreImageOracle, }; use ark_ff::Field; -use log::info; +use log::{debug, info}; use std::array; pub const NUM_GLOBAL_LOOKUP_TERMS: usize = 1; @@ -100,6 +100,15 @@ fn memory_size(total: usize) -> String { impl InterpreterEnv for Env { type Variable = u32; + fn get_instruction_part(&self, part: InstructionPart) -> Self::Variable { + self.instruction_parts[part] + } + + fn set_instruction_pointer(&mut self, ip: Self::Variable) { + self.instruction_pointer = ip; + // Set next instruction pointer? + } + fn constant(x: u32) -> Self::Variable { x } @@ -299,18 +308,30 @@ impl Env { pub fn step(&mut self, config: VmConfiguration, metadata: &Meta, start: &Start) { let (opcode, instruction) = self.decode_instruction(); + let op_code = (instruction >> 26) & ((1 << (32 - 26)) - 1); + let rs = (instruction >> 21) & ((1 << (26 - 21)) - 1); + let rt = (instruction >> 16) & ((1 << (21 - 16)) - 1); + let rd = (instruction >> 11) & ((1 << (16 - 11)) - 1); + let shamt = (instruction >> 6) & ((1 << (11 - 6)) - 1); + let funct = instruction & ((1 << 6) - 1); let instruction_parts: InstructionParts = InstructionParts { - op_code: ((instruction >> 26) & ((1 << (32 - 26)) - 1)), - rs: ((instruction >> 21) & ((1 << (26 - 21)) - 1)), - rt: ((instruction >> 16) & ((1 << (21 - 16)) - 1)), - rd: ((instruction >> 11) & ((1 << (16 - 11)) - 1)), - shamt: ((instruction >> 6) & ((1 << (11 - 6)) - 1)), - funct: (instruction & ((1 << 6) - 1)), + op_code, + rs, + rt, + rd, + shamt, + funct, }; + debug!("instruction: {:?}", opcode); + debug!("Instruction hex: {:#010x}", instruction); + debug!("Instruction: {:#034b}", instruction); + debug!("Rs: {:#07b}", rs); + debug!("Rt: {:#07b}", rt); + debug!("Rd: {:#07b}", rd); + debug!("Shamt: {:#07b}", shamt); + debug!("Funct: {:#08b}", funct); self.instruction_parts = instruction_parts; - println!("instruction: {:?}", opcode); - self.pp_info(config.info_at, metadata, start); // Force stops at given iteration From db56795aeec9556eff5a0bfb95cfe2d900e2680f Mon Sep 17 00:00:00 2001 From: Danny Willems Date: Thu, 30 Nov 2023 22:39:53 +0100 Subject: [PATCH 2/2] Add test for jump --- optimism/src/mips/interpreter.rs | 51 ++++++++++++++++++++++++++++++++ optimism/src/mips/witness.rs | 2 +- 2 files changed, 52 insertions(+), 1 deletion(-) diff --git a/optimism/src/mips/interpreter.rs b/optimism/src/mips/interpreter.rs index 63f53db97c..f7fd1a187f 100644 --- a/optimism/src/mips/interpreter.rs +++ b/optimism/src/mips/interpreter.rs @@ -257,3 +257,54 @@ pub fn interpret_itype(env: &mut Env, instr: ITypeInstructi // TODO: Don't halt. env.set_halted(Env::constant(1)); } + +#[cfg(test)] +mod tests { + + use super::*; + use crate::cannon::HostProgram; + use crate::mips::registers::Registers; + use crate::mips::witness::{Env, SyscallEnv, SCRATCH_SIZE}; + use crate::preimage_oracle::PreImageOracle; + use mina_curves::pasta::Fp; + + fn dummy_env() -> Env { + let host_program = Some(HostProgram { + name: String::from("true"), + arguments: vec![], + }); + let dummy_preimage_oracle = PreImageOracle::create(&host_program); + Env { + instruction_parts: InstructionParts::default(), + instruction_counter: 0, + memory: vec![], + memory_write_index: vec![], + registers: Registers::default(), + registers_write_index: Registers::default(), + instruction_pointer: 0, + next_instruction_pointer: 0, + scratch_state_idx: 0, + scratch_state: [Fp::from(0); SCRATCH_SIZE], + halt: true, + syscall_env: SyscallEnv::default(), + preimage_oracle: dummy_preimage_oracle, + } + } + #[test] + fn test_unit_jump_instruction() { + // We only care about instruction parts and instruction pointer + let mut dummy_env = dummy_env(); + // Instruction: 0b00001000000000101010011001100111 + // j 173671 + dummy_env.instruction_parts = InstructionParts { + op_code: 0b000010, + rs: 0b00000, + rt: 0b00010, + rd: 0b10100, + shamt: 0b11001, + funct: 0b100111, + }; + interpret_jtype(&mut dummy_env, JTypeInstruction::Jump); + assert_eq!(dummy_env.instruction_pointer, 694684); + } +} diff --git a/optimism/src/mips/witness.rs b/optimism/src/mips/witness.rs index 57444bc8a0..a422c7385d 100644 --- a/optimism/src/mips/witness.rs +++ b/optimism/src/mips/witness.rs @@ -23,7 +23,7 @@ pub const NUM_LOOKUP_TERMS: usize = NUM_GLOBAL_LOOKUP_TERMS + NUM_DECODING_LOOKUP_TERMS + NUM_INSTRUCTION_LOOKUP_TERMS; pub const SCRATCH_SIZE: usize = 25; -#[derive(Clone)] +#[derive(Clone, Default)] pub struct SyscallEnv { pub heap: u32, // Heap pointer (actually unused in Cannon as of [2023-10-18]) pub preimage_offset: u32,