Skip to content

Commit

Permalink
Merge pull request #1361 from o1-labs/dw/jump-instruction
Browse files Browse the repository at this point in the history
Implementing jump
  • Loading branch information
dannywillems authored Dec 1, 2023
2 parents 7972ca1 + db56795 commit c827be5
Show file tree
Hide file tree
Showing 2 changed files with 108 additions and 14 deletions.
79 changes: 76 additions & 3 deletions optimism/src/mips/interpreter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,16 @@ pub enum ITypeInstruction {
}

pub trait InterpreterEnv {
type Variable: Clone + std::ops::Add<Self::Variable, Output = Self::Variable>;
type Variable: Clone
+ std::ops::Add<Self::Variable, Output = Self::Variable>
+ std::ops::Mul<u32, Output = Self::Variable>
+ std::ops::Shl<u32, Output = Self::Variable>
+ std::ops::BitAnd<u32, Output = Self::Variable>
+ 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;

Expand Down Expand Up @@ -198,11 +207,24 @@ pub fn interpret_rtype<Env: InterpreterEnv>(env: &mut Env, instr: RTypeInstructi

pub fn interpret_jtype<Env: InterpreterEnv>(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: InterpreterEnv>(env: &mut Env, instr: ITypeInstruction) {
Expand Down Expand Up @@ -235,3 +257,54 @@ pub fn interpret_itype<Env: InterpreterEnv>(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<Fp> {
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);
}
}
43 changes: 32 additions & 11 deletions optimism/src/mips/witness.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,15 @@ use crate::{
},
mips::{
interpreter::{
self, ITypeInstruction, Instruction, InstructionParts, InterpreterEnv,
self, ITypeInstruction, Instruction, InstructionPart, InstructionParts, InterpreterEnv,
JTypeInstruction, RTypeInstruction,
},
registers::Registers,
},
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;
Expand All @@ -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,
Expand Down Expand Up @@ -100,6 +100,15 @@ fn memory_size(total: usize) -> String {
impl<Fp: Field> InterpreterEnv for Env<Fp> {
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
}
Expand Down Expand Up @@ -299,18 +308,30 @@ impl<Fp: Field> Env<Fp> {

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<u32> = 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
Expand Down

0 comments on commit c827be5

Please sign in to comment.