-
Notifications
You must be signed in to change notification settings - Fork 106
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #1298 from o1-labs/feature/add-environment
Add initial `witness::Env` for MIPS VM
- Loading branch information
Showing
7 changed files
with
165 additions
and
3 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,2 @@ | ||
pub mod cannon; | ||
pub mod mips; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
pub mod registers; | ||
pub mod witness; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
use serde::{Deserialize, Serialize}; | ||
use std::ops::{Index, IndexMut}; | ||
|
||
pub const NUM_REGISTERS: usize = 34; | ||
|
||
#[derive(Clone, Default, Debug, Serialize, Deserialize)] | ||
pub struct Registers<T> { | ||
pub general_purpose: [T; 32], | ||
pub hi: T, | ||
pub lo: T, | ||
} | ||
|
||
impl<T> Registers<T> { | ||
pub fn iter(&self) -> impl Iterator<Item = &T> { | ||
self.general_purpose.iter().chain([&self.hi, &self.lo]) | ||
} | ||
} | ||
|
||
impl<T: Clone> Index<usize> for Registers<T> { | ||
type Output = T; | ||
|
||
fn index(&self, index: usize) -> &Self::Output { | ||
if index < 32 { | ||
&self.general_purpose[index] | ||
} else if index == 32 { | ||
&self.hi | ||
} else if index == 33 { | ||
&self.lo | ||
} else { | ||
panic!("Index out of bounds"); | ||
} | ||
} | ||
} | ||
|
||
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 { | ||
&mut self.hi | ||
} else if index == 33 { | ||
&mut self.lo | ||
} else { | ||
panic!("Index out of bounds"); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,99 @@ | ||
use crate::{cannon::State, mips::registers::Registers}; | ||
use ark_ff::Field; | ||
use std::array; | ||
|
||
pub const NUM_GLOBAL_LOOKUP_TERMS: usize = 1; | ||
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 = 25; | ||
|
||
#[derive(Clone)] | ||
pub struct SyscallEnv { | ||
pub heap: u32, // Heap pointer (actually unused in Cannon as of [2023-10-18]) | ||
pub preimage_offset: u32, | ||
pub preimage_key: Vec<u8>, | ||
pub last_hint: Option<Vec<u8>>, | ||
} | ||
|
||
impl SyscallEnv { | ||
pub fn create(state: &State) -> Self { | ||
SyscallEnv { | ||
heap: state.heap, | ||
preimage_key: state.preimage_key.as_bytes().to_vec(), // Might not be correct | ||
preimage_offset: state.preimage_offset, | ||
last_hint: state.last_hint.clone(), | ||
} | ||
} | ||
} | ||
|
||
#[derive(Clone)] | ||
pub struct Env<Fp> { | ||
pub instruction_counter: usize, | ||
pub memory: Vec<(u32, Vec<u8>)>, | ||
pub memory_write_index: Vec<(u32, Vec<usize>)>, | ||
pub registers: Registers<u32>, | ||
pub registers_write_index: Registers<usize>, | ||
pub instruction_pointer: u32, | ||
pub scratch_state_idx: usize, | ||
pub scratch_state: [Fp; SCRATCH_SIZE], | ||
pub halt: bool, | ||
pub syscall_env: SyscallEnv, | ||
} | ||
|
||
fn fresh_scratch_state<Fp: Field, const N: usize>() -> [Fp; N] { | ||
array::from_fn(|_| Fp::zero()) | ||
} | ||
|
||
impl<Fp: Field> Env<Fp> { | ||
pub fn create(page_size: usize, state: State) -> Self { | ||
let initial_instruction_pointer = state.pc; | ||
|
||
let syscall_env = SyscallEnv::create(&state); | ||
|
||
let mut initial_memory: Vec<(u32, Vec<u8>)> = state | ||
.memory | ||
.into_iter() | ||
// Check that the conversion from page data is correct | ||
.map(|page| (page.index, page.data)) | ||
.collect(); | ||
|
||
for (_address, initial_memory) in initial_memory.iter_mut() { | ||
initial_memory.extend((0..(page_size - initial_memory.len())).map(|_| 0u8)); | ||
assert_eq!(initial_memory.len(), page_size); | ||
} | ||
|
||
let memory_offsets = initial_memory | ||
.iter() | ||
.map(|(offset, _)| *offset) | ||
.collect::<Vec<_>>(); | ||
|
||
let initial_registers = Registers { | ||
lo: state.lo, | ||
hi: state.hi, | ||
general_purpose: state.registers, | ||
}; | ||
|
||
Env { | ||
instruction_counter: state.step as usize, | ||
memory: initial_memory.clone(), | ||
memory_write_index: memory_offsets | ||
.iter() | ||
.map(|offset| (*offset, vec![0usize; page_size])) | ||
.collect(), | ||
registers: initial_registers.clone(), | ||
registers_write_index: Registers::default(), | ||
instruction_pointer: initial_instruction_pointer, | ||
scratch_state_idx: 0, | ||
scratch_state: fresh_scratch_state(), | ||
halt: state.exited, | ||
syscall_env, | ||
} | ||
} | ||
|
||
pub fn step(&mut self) { | ||
// TODO | ||
self.halt = true; | ||
} | ||
} |