Skip to content

Commit

Permalink
Merge pull request #1405 from o1-labs/feature/ips-as-registers
Browse files Browse the repository at this point in the history
Store instruction pointers in registers
  • Loading branch information
dannywillems authored Dec 5, 2023
2 parents c1cae67 + 4af60ce commit a03e597
Show file tree
Hide file tree
Showing 3 changed files with 95 additions and 37 deletions.
61 changes: 57 additions & 4 deletions optimism/src/mips/interpreter.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use crate::mips::registers::{REGISTER_CURRENT_IP, REGISTER_NEXT_IP};
use log::debug;
use strum_macros::{EnumCount, EnumIter};

Expand Down Expand Up @@ -397,13 +398,65 @@ pub trait InterpreterEnv {
// TODO
}

fn set_instruction_pointer(&mut self, ip: Self::Variable);
fn set_instruction_pointer(&mut self, ip: Self::Variable) {
let idx = Self::constant(REGISTER_CURRENT_IP as u32);
let new_accessed = self.instruction_counter() + Self::constant(1);
unsafe {
self.push_register_access(&idx, new_accessed.clone());
}
unsafe {
self.push_register(&idx, ip.clone());
}
self.add_lookup(Lookup {
numerator: -1,
table_id: LookupTable::RegisterLookup,
value: vec![idx, new_accessed, ip],
});
}

fn get_instruction_pointer(&self) -> Self::Variable;
fn get_instruction_pointer(&mut self) -> Self::Variable {
let idx = Self::constant(REGISTER_CURRENT_IP as u32);
let ip = {
let value_location = self.alloc_scratch();
unsafe { self.fetch_register(&idx, value_location) }
};
self.add_lookup(Lookup {
numerator: 1,
table_id: LookupTable::RegisterLookup,
value: vec![idx, self.instruction_counter(), ip.clone()],
});
ip
}

fn set_next_instruction_pointer(&mut self, ip: Self::Variable);
fn set_next_instruction_pointer(&mut self, ip: Self::Variable) {
let idx = Self::constant(REGISTER_NEXT_IP as u32);
let new_accessed = self.instruction_counter() + Self::constant(1);
unsafe {
self.push_register_access(&idx, new_accessed.clone());
}
unsafe {
self.push_register(&idx, ip.clone());
}
self.add_lookup(Lookup {
numerator: -1,
table_id: LookupTable::RegisterLookup,
value: vec![idx, new_accessed, ip],
});
}

fn get_next_instruction_pointer(&self) -> Self::Variable;
fn get_next_instruction_pointer(&mut self) -> Self::Variable {
let idx = Self::constant(REGISTER_NEXT_IP as u32);
let ip = {
let value_location = self.alloc_scratch();
unsafe { self.fetch_register(&idx, value_location) }
};
self.add_lookup(Lookup {
numerator: 1,
table_id: LookupTable::RegisterLookup,
value: vec![idx, self.instruction_counter(), ip.clone()],
});
ip
}

fn constant(x: u32) -> Self::Variable;

Expand Down
32 changes: 26 additions & 6 deletions optimism/src/mips/registers.rs
Original file line number Diff line number Diff line change
@@ -1,18 +1,30 @@
use serde::{Deserialize, Serialize};
use std::ops::{Index, IndexMut};

pub const NUM_REGISTERS: usize = 34;
pub const REGISTER_HI: usize = 32;
pub const REGISTER_LO: usize = 33;
pub const REGISTER_CURRENT_IP: usize = 34;
pub const REGISTER_NEXT_IP: usize = 35;

pub const NUM_REGISTERS: usize = 36;

#[derive(Clone, Default, Debug, Serialize, Deserialize)]
pub struct Registers<T> {
pub general_purpose: [T; 32],
pub hi: T,
pub lo: T,
pub current_instruction_pointer: T,
pub next_instruction_pointer: T,
}

impl<T> Registers<T> {
pub fn iter(&self) -> impl Iterator<Item = &T> {
self.general_purpose.iter().chain([&self.hi, &self.lo])
self.general_purpose.iter().chain([
&self.hi,
&self.lo,
&self.current_instruction_pointer,
&self.next_instruction_pointer,
])
}
}

Expand All @@ -22,10 +34,14 @@ impl<T: Clone> Index<usize> for Registers<T> {
fn index(&self, index: usize) -> &Self::Output {
if index < 32 {
&self.general_purpose[index]
} else if index == 32 {
} else if index == REGISTER_HI {
&self.hi
} else if index == 33 {
} else if index == REGISTER_LO {
&self.lo
} else if index == REGISTER_CURRENT_IP {
&self.current_instruction_pointer
} else if index == REGISTER_NEXT_IP {
&self.next_instruction_pointer
} else {
panic!("Index out of bounds");
}
Expand All @@ -36,10 +52,14 @@ impl<T: Clone> IndexMut<usize> for Registers<T> {
fn index_mut(&mut self, index: usize) -> &mut Self::Output {
if index < 32 {
&mut self.general_purpose[index]
} else if index == 32 {
} else if index == REGISTER_HI {
&mut self.hi
} else if index == 33 {
} else if index == REGISTER_LO {
&mut self.lo
} else if index == REGISTER_CURRENT_IP {
&mut self.current_instruction_pointer
} else if index == REGISTER_NEXT_IP {
&mut self.next_instruction_pointer
} else {
panic!("Index out of bounds");
}
Expand Down
39 changes: 12 additions & 27 deletions optimism/src/mips/witness.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ pub const NUM_DECODING_LOOKUP_TERMS: usize = 2;
pub const NUM_INSTRUCTION_LOOKUP_TERMS: usize = 5;
pub const NUM_LOOKUP_TERMS: usize =
NUM_GLOBAL_LOOKUP_TERMS + NUM_DECODING_LOOKUP_TERMS + NUM_INSTRUCTION_LOOKUP_TERMS;
pub const SCRATCH_SIZE: usize = 29;
pub const SCRATCH_SIZE: usize = 31;

#[derive(Clone, Default)]
pub struct SyscallEnv {
Expand All @@ -49,8 +49,6 @@ pub struct Env<Fp> {
pub memory_write_index: Vec<(u32, Vec<u32>)>, // TODO: u32 will not be big enough..
pub registers: Registers<u32>,
pub registers_write_index: Registers<u32>, // TODO: u32 will not be big enough..
pub instruction_pointer: u32,
pub next_instruction_pointer: u32,
pub scratch_state_idx: usize,
pub scratch_state: [Fp; SCRATCH_SIZE],
pub halt: bool,
Expand Down Expand Up @@ -202,22 +200,6 @@ impl<Fp: Field> InterpreterEnv for Env<Fp> {
panic!("Could not write to address")
}

fn set_instruction_pointer(&mut self, ip: Self::Variable) {
self.instruction_pointer = ip;
}

fn get_instruction_pointer(&self) -> Self::Variable {
self.instruction_pointer
}

fn set_next_instruction_pointer(&mut self, ip: Self::Variable) {
self.next_instruction_pointer = ip;
}

fn get_next_instruction_pointer(&self) -> Self::Variable {
self.next_instruction_pointer
}

fn constant(x: u32) -> Self::Variable {
x
}
Expand Down Expand Up @@ -284,6 +266,8 @@ impl<Fp: Field> Env<Fp> {
lo: state.lo,
hi: state.hi,
general_purpose: state.registers,
current_instruction_pointer: initial_instruction_pointer,
next_instruction_pointer,
};

Env {
Expand All @@ -295,8 +279,6 @@ impl<Fp: Field> Env<Fp> {
.collect(),
registers: initial_registers.clone(),
registers_write_index: Registers::default(),
instruction_pointer: initial_instruction_pointer,
next_instruction_pointer,
scratch_state_idx: 0,
scratch_state: fresh_scratch_state(),
halt: state.exited,
Expand Down Expand Up @@ -328,10 +310,13 @@ impl<Fp: Field> Env<Fp> {
}

pub fn decode_instruction(&self) -> (Instruction, u32) {
let instruction = ((self.get_memory_direct(self.instruction_pointer) as u32) << 24)
| ((self.get_memory_direct(self.instruction_pointer + 1) as u32) << 16)
| ((self.get_memory_direct(self.instruction_pointer + 2) as u32) << 8)
| (self.get_memory_direct(self.instruction_pointer + 3) as u32);
let instruction =
((self.get_memory_direct(self.registers.current_instruction_pointer) as u32) << 24)
| ((self.get_memory_direct(self.registers.current_instruction_pointer + 1) as u32)
<< 16)
| ((self.get_memory_direct(self.registers.current_instruction_pointer + 2) as u32)
<< 8)
| (self.get_memory_direct(self.registers.current_instruction_pointer + 3) as u32);
let opcode = {
match instruction >> 26 {
0x00 => match instruction & 0x3F {
Expand Down Expand Up @@ -490,7 +475,7 @@ impl<Fp: Field> Env<Fp> {
}

fn page_address(&self) -> (u32, usize) {
let address = self.instruction_pointer;
let address = self.registers.current_instruction_pointer;
let page = address >> PAGE_ADDRESS_SIZE;
let page_address = (address & PAGE_ADDRESS_MASK) as usize;
(page, page_address)
Expand All @@ -513,7 +498,7 @@ impl<Fp: Field> Env<Fp> {
if self.should_trigger_at(at) {
let elapsed = start.time.elapsed();
let step = self.instruction_counter;
let pc = self.instruction_pointer;
let pc = self.registers.current_instruction_pointer;

// Get the 32-bits opcode
let insn = self.get_opcode().unwrap();
Expand Down

0 comments on commit a03e597

Please sign in to comment.