From f55c75187b2fcc62d9a0107ab29a3e4e3154bef1 Mon Sep 17 00:00:00 2001 From: Danny Willems Date: Fri, 1 Dec 2023 11:27:32 +0100 Subject: [PATCH 01/19] Implement lw --- optimism/src/mips/interpreter.rs | 47 ++++++++++++++++++++++++++++---- optimism/src/mips/witness.rs | 12 ++++++++ 2 files changed, 54 insertions(+), 5 deletions(-) diff --git a/optimism/src/mips/interpreter.rs b/optimism/src/mips/interpreter.rs index f7fd1a187f..77613efdb4 100644 --- a/optimism/src/mips/interpreter.rs +++ b/optimism/src/mips/interpreter.rs @@ -140,8 +140,12 @@ pub trait InterpreterEnv { + std::ops::BitAnd + std::fmt::Display; + fn overwrite_register_checked(&mut self, register_idx: &Self::Variable, value: &Self::Variable); + fn set_instruction_pointer(&mut self, ip: Self::Variable); + fn get_instruction_pointer(&self) -> Self::Variable; + fn get_instruction_part(&self, part: InstructionPart) -> Self::Variable; fn constant(x: u32) -> Self::Variable; @@ -220,11 +224,13 @@ pub fn interpret_jtype(env: &mut Env, instr: JTypeInstructi + (env.get_instruction_part(InstructionPart::Shamt) << 6) + (env.get_instruction_part(InstructionPart::Funct)); env.set_instruction_pointer(addr * 4); + // REMOVEME: when all jtype instructions are implemented. + return; } JTypeInstruction::JumpAndLink => (), }; - // TODO: Don't halt. - // env.set_halted(Env::constant(1)); + // REMOVEME: when all jtype instructions are implemented. + env.set_halted(Env::constant(1)); } pub fn interpret_itype(env: &mut Env, instr: ITypeInstruction) { @@ -243,7 +249,17 @@ pub fn interpret_itype(env: &mut Env, instr: ITypeInstructi ITypeInstruction::LoadUpperImmediate => (), ITypeInstruction::Load8 => (), ITypeInstruction::Load16 => (), - ITypeInstruction::Load32 => (), + ITypeInstruction::Load32 => { + let rt = env.get_instruction_part(InstructionPart::RT); + // Values are the first 16bits + let immediate_value = (env.get_instruction_part(InstructionPart::RD) << 11) + + (env.get_instruction_part(InstructionPart::Shamt) << 6) + + (env.get_instruction_part(InstructionPart::Funct)); + env.overwrite_register_checked(&rt, &immediate_value); + env.set_instruction_pointer(env.get_instruction_pointer() + Env::constant(4u32)); + // REMOVEME: when all itype instructions are implemented. + return; + } ITypeInstruction::Load8Unsigned => (), ITypeInstruction::Load16Unsigned => (), ITypeInstruction::LoadWordLeft => (), @@ -254,8 +270,9 @@ pub fn interpret_itype(env: &mut Env, instr: ITypeInstructi ITypeInstruction::StoreWordLeft => (), ITypeInstruction::StoreWordRight => (), }; - // TODO: Don't halt. - env.set_halted(Env::constant(1)); + + // REMOVEME: when all itype instructions are implemented. + env.set_halted(Env::constant(1)) } #[cfg(test)] @@ -290,6 +307,7 @@ mod tests { preimage_oracle: dummy_preimage_oracle, } } + #[test] fn test_unit_jump_instruction() { // We only care about instruction parts and instruction pointer @@ -307,4 +325,23 @@ mod tests { interpret_jtype(&mut dummy_env, JTypeInstruction::Jump); assert_eq!(dummy_env.instruction_pointer, 694684); } + + #[test] + fn test_unit_load32_instruction() { + // We only care about instruction parts and instruction pointer + let mut dummy_env = dummy_env(); + // Instruction: 0b10001111101001000000000000000000 + // lw $a0, 0 + // a0 = 4 + dummy_env.instruction_parts = InstructionParts { + op_code: 0b000010, + rs: 0b11101, + rt: 0b00100, + rd: 0b00000, + shamt: 0b00000, + funct: 0b000000, + }; + interpret_itype(&mut dummy_env, ITypeInstruction::Load32); + assert_eq!(dummy_env.registers[4], 0); + } } diff --git a/optimism/src/mips/witness.rs b/optimism/src/mips/witness.rs index a422c7385d..49a90afd23 100644 --- a/optimism/src/mips/witness.rs +++ b/optimism/src/mips/witness.rs @@ -100,6 +100,14 @@ fn memory_size(total: usize) -> String { impl InterpreterEnv for Env { type Variable = u32; + fn overwrite_register_checked( + &mut self, + register_idx: &Self::Variable, + value: &Self::Variable, + ) { + self.registers[*register_idx as usize] = *value + } + fn get_instruction_part(&self, part: InstructionPart) -> Self::Variable { self.instruction_parts[part] } @@ -109,6 +117,10 @@ impl InterpreterEnv for Env { // Set next instruction pointer? } + fn get_instruction_pointer(&self) -> Self::Variable { + self.instruction_pointer + } + fn constant(x: u32) -> Self::Variable { x } From e5c1885f1df32f4e15dfe406b7d16e22658cd12a Mon Sep 17 00:00:00 2001 From: Danny Willems Date: Fri, 1 Dec 2023 11:57:41 +0100 Subject: [PATCH 02/19] Add constants for registers --- optimism/src/mips/interpreter.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/optimism/src/mips/interpreter.rs b/optimism/src/mips/interpreter.rs index 77613efdb4..bd01ce3fd8 100644 --- a/optimism/src/mips/interpreter.rs +++ b/optimism/src/mips/interpreter.rs @@ -10,6 +10,10 @@ pub const FD_HINT_WRITE: u32 = 4; pub const FD_PREIMAGE_READ: u32 = 5; pub const FD_PREIMAGE_WRITE: u32 = 6; +pub const REGISTER_A0: u32 = 4; +pub const REGISTER_A1: u32 = 5; +pub const REGISTER_SP: u32 = 29; + #[derive(Debug, Clone, Copy, Eq, PartialEq, EnumCount, EnumIter)] pub enum InstructionPart { OpCode, From 7786a2221c69a889a40b04d27864a5ce38cf54c5 Mon Sep 17 00:00:00 2001 From: Danny Willems Date: Fri, 1 Dec 2023 11:57:57 +0100 Subject: [PATCH 03/19] Export get_immediate code --- optimism/src/mips/interpreter.rs | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/optimism/src/mips/interpreter.rs b/optimism/src/mips/interpreter.rs index bd01ce3fd8..5ab1840487 100644 --- a/optimism/src/mips/interpreter.rs +++ b/optimism/src/mips/interpreter.rs @@ -148,6 +148,13 @@ pub trait InterpreterEnv { fn set_instruction_pointer(&mut self, ip: Self::Variable); + fn get_immediate(&self) -> Self::Variable { + // The immediate value is the first 16bits + (self.get_instruction_part(InstructionPart::RD) << 11) + + (self.get_instruction_part(InstructionPart::Shamt) << 6) + + (self.get_instruction_part(InstructionPart::Funct)) + } + fn get_instruction_pointer(&self) -> Self::Variable; fn get_instruction_part(&self, part: InstructionPart) -> Self::Variable; @@ -255,10 +262,7 @@ pub fn interpret_itype(env: &mut Env, instr: ITypeInstructi ITypeInstruction::Load16 => (), ITypeInstruction::Load32 => { let rt = env.get_instruction_part(InstructionPart::RT); - // Values are the first 16bits - let immediate_value = (env.get_instruction_part(InstructionPart::RD) << 11) - + (env.get_instruction_part(InstructionPart::Shamt) << 6) - + (env.get_instruction_part(InstructionPart::Funct)); + let immediate_value = env.get_immediate(); env.overwrite_register_checked(&rt, &immediate_value); env.set_instruction_pointer(env.get_instruction_pointer() + Env::constant(4u32)); // REMOVEME: when all itype instructions are implemented. From b913a1a2bcfcefa6329eced4aa5e343e7b5a5f97 Mon Sep 17 00:00:00 2001 From: Danny Willems Date: Fri, 1 Dec 2023 11:58:11 +0100 Subject: [PATCH 04/19] Add TODO related to next_instruction_pointer --- optimism/src/mips/interpreter.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/optimism/src/mips/interpreter.rs b/optimism/src/mips/interpreter.rs index 5ab1840487..93b02eaa2c 100644 --- a/optimism/src/mips/interpreter.rs +++ b/optimism/src/mips/interpreter.rs @@ -265,6 +265,7 @@ pub fn interpret_itype(env: &mut Env, instr: ITypeInstructi let immediate_value = env.get_immediate(); env.overwrite_register_checked(&rt, &immediate_value); env.set_instruction_pointer(env.get_instruction_pointer() + Env::constant(4u32)); + // TODO: update next_instruction_pointer // REMOVEME: when all itype instructions are implemented. return; } From dfa4ffa80aeaa6d9c31ee275eae9829697d881f1 Mon Sep 17 00:00:00 2001 From: Danny Willems Date: Fri, 1 Dec 2023 11:58:28 +0100 Subject: [PATCH 05/19] Implement fetch_register_checked --- optimism/src/mips/interpreter.rs | 2 ++ optimism/src/mips/witness.rs | 4 ++++ 2 files changed, 6 insertions(+) diff --git a/optimism/src/mips/interpreter.rs b/optimism/src/mips/interpreter.rs index 93b02eaa2c..6105d4fc28 100644 --- a/optimism/src/mips/interpreter.rs +++ b/optimism/src/mips/interpreter.rs @@ -146,6 +146,8 @@ pub trait InterpreterEnv { fn overwrite_register_checked(&mut self, register_idx: &Self::Variable, value: &Self::Variable); + fn fetch_register_checked(&self, register_idx: &Self::Variable) -> Self::Variable; + fn set_instruction_pointer(&mut self, ip: Self::Variable); fn get_immediate(&self) -> Self::Variable { diff --git a/optimism/src/mips/witness.rs b/optimism/src/mips/witness.rs index 49a90afd23..19b56a3aaf 100644 --- a/optimism/src/mips/witness.rs +++ b/optimism/src/mips/witness.rs @@ -108,6 +108,10 @@ impl InterpreterEnv for Env { self.registers[*register_idx as usize] = *value } + fn fetch_register_checked(&self, register_idx: &Self::Variable) -> Self::Variable { + self.registers[*register_idx as usize] + } + fn get_instruction_part(&self, part: InstructionPart) -> Self::Variable { self.instruction_parts[part] } From ed204da4da9b8f48c4e53a6cdb418ff0b9f21f1f Mon Sep 17 00:00:00 2001 From: Danny Willems Date: Fri, 1 Dec 2023 11:58:40 +0100 Subject: [PATCH 06/19] Implement addi --- optimism/src/mips/interpreter.rs | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/optimism/src/mips/interpreter.rs b/optimism/src/mips/interpreter.rs index 6105d4fc28..3df99ee1a2 100644 --- a/optimism/src/mips/interpreter.rs +++ b/optimism/src/mips/interpreter.rs @@ -252,7 +252,18 @@ pub fn interpret_itype(env: &mut Env, instr: ITypeInstructi ITypeInstruction::BranchNeq => (), ITypeInstruction::BranchLeqZero => (), ITypeInstruction::BranchGtZero => (), - ITypeInstruction::AddImmediate => (), + ITypeInstruction::AddImmediate => { + let rs = env.get_instruction_part(InstructionPart::RS); + let register_rs = env.fetch_register_checked(&rs); + let imm = env.get_immediate(); + let res = register_rs + imm; + let rt = env.get_instruction_part(InstructionPart::RT); + env.overwrite_register_checked(&rt, &res); + env.set_instruction_pointer(env.get_instruction_pointer() + Env::constant(4u32)); + // TODO: update next_instruction_pointer + // REMOVEME: when all itype instructions are implemented. + return; + } ITypeInstruction::AddImmediateUnsigned => (), ITypeInstruction::SetLessThanImmediate => (), ITypeInstruction::SetLessThanImmediateUnsigned => (), From 9ee1c22fe68e414da4ceaa66f7f9125ce2de560c Mon Sep 17 00:00:00 2001 From: Danny Willems Date: Fri, 1 Dec 2023 11:58:58 +0100 Subject: [PATCH 07/19] Use register constants --- optimism/src/mips/interpreter.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/optimism/src/mips/interpreter.rs b/optimism/src/mips/interpreter.rs index 3df99ee1a2..29f9c419cc 100644 --- a/optimism/src/mips/interpreter.rs +++ b/optimism/src/mips/interpreter.rs @@ -364,6 +364,6 @@ mod tests { funct: 0b000000, }; interpret_itype(&mut dummy_env, ITypeInstruction::Load32); - assert_eq!(dummy_env.registers[4], 0); + assert_eq!(dummy_env.registers[REGISTER_A0 as usize], 0); } } From 1cae34b5303c9a4ce93d3ff8ca159913ac6c1b4e Mon Sep 17 00:00:00 2001 From: Danny Willems Date: Fri, 1 Dec 2023 11:59:07 +0100 Subject: [PATCH 08/19] Test addi instruction --- optimism/src/mips/interpreter.rs | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/optimism/src/mips/interpreter.rs b/optimism/src/mips/interpreter.rs index 29f9c419cc..8b51825cb7 100644 --- a/optimism/src/mips/interpreter.rs +++ b/optimism/src/mips/interpreter.rs @@ -366,4 +366,25 @@ mod tests { interpret_itype(&mut dummy_env, ITypeInstruction::Load32); assert_eq!(dummy_env.registers[REGISTER_A0 as usize], 0); } + + #[test] + fn test_unit_addi_instruction() { + // We only care about instruction parts and instruction pointer + let mut dummy_env = dummy_env(); + // Instruction: 0b10001111101001000000000000000000 + // addi a1,sp,4 + dummy_env.instruction_parts = InstructionParts { + op_code: 0b000010, + rs: 0b11101, + rt: 0b00101, + rd: 0b00000, + shamt: 0b00000, + funct: 0b000100, + }; + interpret_itype(&mut dummy_env, ITypeInstruction::AddImmediate); + assert_eq!( + dummy_env.registers[REGISTER_A1 as usize], + dummy_env.registers[REGISTER_SP as usize] + 4 + ); + } } From 052a84ba564da439fa51de0b929e6170cc639744 Mon Sep 17 00:00:00 2001 From: Danny Willems Date: Fri, 1 Dec 2023 12:01:10 +0100 Subject: [PATCH 09/19] Fix the wording for the bits position --- optimism/src/mips/interpreter.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/optimism/src/mips/interpreter.rs b/optimism/src/mips/interpreter.rs index 8b51825cb7..400749190e 100644 --- a/optimism/src/mips/interpreter.rs +++ b/optimism/src/mips/interpreter.rs @@ -151,7 +151,7 @@ pub trait InterpreterEnv { fn set_instruction_pointer(&mut self, ip: Self::Variable); fn get_immediate(&self) -> Self::Variable { - // The immediate value is the first 16bits + // The immediate value is the last 16bits (self.get_instruction_part(InstructionPart::RD) << 11) + (self.get_instruction_part(InstructionPart::Shamt) << 6) + (self.get_instruction_part(InstructionPart::Funct)) From a9f69bb07a95f6ea79d48143d5625318209ee037 Mon Sep 17 00:00:00 2001 From: Danny Willems Date: Fri, 1 Dec 2023 12:12:29 +0100 Subject: [PATCH 10/19] Add more constants regarding the registers --- optimism/src/mips/interpreter.rs | 56 ++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/optimism/src/mips/interpreter.rs b/optimism/src/mips/interpreter.rs index 400749190e..078197faa4 100644 --- a/optimism/src/mips/interpreter.rs +++ b/optimism/src/mips/interpreter.rs @@ -10,9 +10,65 @@ pub const FD_HINT_WRITE: u32 = 4; pub const FD_PREIMAGE_READ: u32 = 5; pub const FD_PREIMAGE_WRITE: u32 = 6; +// Source: https://www.doc.ic.ac.uk/lab/secondyear/spim/node10.html +// Reserved for assembler +pub const REGISTER_AT: u32 = 1; +// Argument 0 pub const REGISTER_A0: u32 = 4; +// Argument 1 pub const REGISTER_A1: u32 = 5; +// Argument 2 +pub const REGISTER_A2: u32 = 6; +// Argument 3 +pub const REGISTER_A3: u32 = 7; +// Temporary (not preserved across call) +pub const REGISTER_T0: u32 = 8; +// Temporary (not preserved across call) +pub const REGISTER_T1: u32 = 9; +// Temporary (not preserved across call) +pub const REGISTER_T2: u32 = 10; +// Temporary (not preserved across call) +pub const REGISTER_T3: u32 = 11; +// Temporary (not preserved across call) +pub const REGISTER_T4: u32 = 12; +// Temporary (not preserved across call) +pub const REGISTER_T5: u32 = 13; +// Temporary (not preserved across call) +pub const REGISTER_T6: u32 = 14; +// Temporary (not preserved across call) +pub const REGISTER_T7: u32 = 15; +// Saved temporary (preserved across call) +pub const REGISTER_S0: u32 = 16; +// Saved temporary (preserved across call) +pub const REGISTER_S1: u32 = 17; +// Saved temporary (preserved across call) +pub const REGISTER_S2: u32 = 18; +// Saved temporary (preserved across call) +pub const REGISTER_S3: u32 = 19; +// Saved temporary (preserved across call) +pub const REGISTER_S4: u32 = 20; +// Saved temporary (preserved across call) +pub const REGISTER_S5: u32 = 21; +// Saved temporary (preserved across call) +pub const REGISTER_S6: u32 = 22; +// Saved temporary (preserved across call) +pub const REGISTER_S7: u32 = 23; +// Temporary (not preserved across call) +pub const REGISTER_T8: u32 = 24; +// Temporary (not preserved across call) +pub const REGISTER_T9: u32 = 25; +// Reserved for OS kernel +pub const REGISTER_K0: u32 = 26; +// Reserved for OS kernel +pub const REGISTER_K1: u32 = 27; +// Pointer to global area +pub const REGISTER_GP: u32 = 28; +// Stack pointer pub const REGISTER_SP: u32 = 29; +// Frame pointer +pub const REGISTER_FP: u32 = 30; +// Return address (used by function call) +pub const REGISTER_RA: u32 = 31; #[derive(Debug, Clone, Copy, Eq, PartialEq, EnumCount, EnumIter)] pub enum InstructionPart { From 168e21876bf2ae348709ea446d48de2c0b25b35c Mon Sep 17 00:00:00 2001 From: Danny Willems Date: Fri, 1 Dec 2023 12:59:59 +0100 Subject: [PATCH 11/19] Add lui --- optimism/src/mips/interpreter.rs | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/optimism/src/mips/interpreter.rs b/optimism/src/mips/interpreter.rs index 078197faa4..4fc71c6f3f 100644 --- a/optimism/src/mips/interpreter.rs +++ b/optimism/src/mips/interpreter.rs @@ -326,7 +326,16 @@ pub fn interpret_itype(env: &mut Env, instr: ITypeInstructi ITypeInstruction::AndImmediate => (), ITypeInstruction::OrImmediate => (), ITypeInstruction::XorImmediate => (), - ITypeInstruction::LoadUpperImmediate => (), + ITypeInstruction::LoadUpperImmediate => { + // lui $reg, [most significant 16 bits of immediate] + let rt = env.get_instruction_part(InstructionPart::RT); + let immediate_value = env.get_immediate(); + env.overwrite_register_checked(&rt, &immediate_value); + env.set_instruction_pointer(env.get_instruction_pointer() + Env::constant(4u32)); + // TODO: update next_instruction_pointer + // REMOVEME: when all itype instructions are implemented. + return; + }, ITypeInstruction::Load8 => (), ITypeInstruction::Load16 => (), ITypeInstruction::Load32 => { From e153d86e1c8dd87aefaf1eb7efbc99e745626a5f Mon Sep 17 00:00:00 2001 From: Danny Willems Date: Fri, 1 Dec 2023 13:00:10 +0100 Subject: [PATCH 12/19] Add tests for lui --- optimism/src/mips/interpreter.rs | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/optimism/src/mips/interpreter.rs b/optimism/src/mips/interpreter.rs index 4fc71c6f3f..1c5898c8eb 100644 --- a/optimism/src/mips/interpreter.rs +++ b/optimism/src/mips/interpreter.rs @@ -452,4 +452,25 @@ mod tests { dummy_env.registers[REGISTER_SP as usize] + 4 ); } + + #[test] + fn test_unit_lui_instruction() { + // We only care about instruction parts and instruction pointer + let mut dummy_env = dummy_env(); + // Instruction: 0b00111100000000010000000000001010 + // lui at,0xa + dummy_env.instruction_parts = InstructionParts { + op_code: 0b000010, + rs: 0b00000, + rt: 0b00001, + rd: 0b00000, + shamt: 0b00000, + funct: 0b001010, + }; + interpret_itype(&mut dummy_env, ITypeInstruction::LoadUpperImmediate); + assert_eq!( + dummy_env.registers[REGISTER_AT as usize], + 0xa, + ); + } } From ac2be11ef20835bcc5f2f49443589963afde724d Mon Sep 17 00:00:00 2001 From: Danny Willems Date: Fri, 1 Dec 2023 13:22:06 +0100 Subject: [PATCH 13/19] lui: the value must be loaded in the upper 16bits --- optimism/src/mips/interpreter.rs | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/optimism/src/mips/interpreter.rs b/optimism/src/mips/interpreter.rs index 1c5898c8eb..2d707286a0 100644 --- a/optimism/src/mips/interpreter.rs +++ b/optimism/src/mips/interpreter.rs @@ -329,13 +329,13 @@ pub fn interpret_itype(env: &mut Env, instr: ITypeInstructi ITypeInstruction::LoadUpperImmediate => { // lui $reg, [most significant 16 bits of immediate] let rt = env.get_instruction_part(InstructionPart::RT); - let immediate_value = env.get_immediate(); + let immediate_value = env.get_immediate() << 16; env.overwrite_register_checked(&rt, &immediate_value); env.set_instruction_pointer(env.get_instruction_pointer() + Env::constant(4u32)); // TODO: update next_instruction_pointer // REMOVEME: when all itype instructions are implemented. return; - }, + } ITypeInstruction::Load8 => (), ITypeInstruction::Load16 => (), ITypeInstruction::Load32 => { @@ -468,9 +468,6 @@ mod tests { funct: 0b001010, }; interpret_itype(&mut dummy_env, ITypeInstruction::LoadUpperImmediate); - assert_eq!( - dummy_env.registers[REGISTER_AT as usize], - 0xa, - ); + assert_eq!(dummy_env.registers[REGISTER_AT as usize], 0xa0000,); } } From 5b9ccb2fb3ea2698b90132017c5a1c447a8a00f9 Mon Sep 17 00:00:00 2001 From: Danny Willems Date: Fri, 1 Dec 2023 14:08:06 +0100 Subject: [PATCH 14/19] Extract constants regarding memory --- optimism/src/cannon.rs | 8 ++++---- optimism/src/main.rs | 2 +- optimism/src/mips/witness.rs | 7 ++----- 3 files changed, 7 insertions(+), 10 deletions(-) diff --git a/optimism/src/cannon.rs b/optimism/src/cannon.rs index 2a60a21818..fad8b94c52 100644 --- a/optimism/src/cannon.rs +++ b/optimism/src/cannon.rs @@ -7,9 +7,9 @@ use regex::Regex; use serde::{Deserialize, Deserializer, Serialize}; use std::io::Read; -pub const PAGE_ADDRESS_SIZE: usize = 12; -pub const PAGE_SIZE: usize = 1 << PAGE_ADDRESS_SIZE; -pub const PAGE_ADDRESS_MASK: usize = PAGE_SIZE - 1; +pub const PAGE_ADDRESS_SIZE: u32 = 12; +pub const PAGE_SIZE: u32 = 1 << PAGE_ADDRESS_SIZE; +pub const PAGE_ADDRESS_MASK: u32 = PAGE_SIZE - 1; #[derive(Serialize, Deserialize, Debug)] pub struct Page { @@ -27,7 +27,7 @@ where let mut decoder = Decoder::new(&b64_decoded[..]).unwrap(); let mut data = Vec::new(); decoder.read_to_end(&mut data).unwrap(); - assert_eq!(data.len(), PAGE_SIZE); + assert_eq!(data.len(), PAGE_SIZE as usize); Ok(data) } diff --git a/optimism/src/main.rs b/optimism/src/main.rs index 977bbfb256..c8bb5e85af 100644 --- a/optimism/src/main.rs +++ b/optimism/src/main.rs @@ -143,7 +143,7 @@ pub fn main() -> ExitCode { env_logger::Builder::from_env(env_logger::Env::default().default_filter_or("info")).init(); - let mut env = witness::Env::::create(cannon::PAGE_SIZE, state, po); + let mut env = witness::Env::::create(cannon::PAGE_SIZE as usize, state, po); while !env.halt { env.step(configuration.clone(), &meta, &start); diff --git a/optimism/src/mips/witness.rs b/optimism/src/mips/witness.rs index 19b56a3aaf..38255048e9 100644 --- a/optimism/src/mips/witness.rs +++ b/optimism/src/mips/witness.rs @@ -193,9 +193,6 @@ impl Env { } pub fn get_memory_direct(&self, addr: u32) -> u8 { - const PAGE_ADDRESS_SIZE: u32 = 12; - const PAGE_SIZE: u32 = 1 << PAGE_ADDRESS_SIZE; - const PAGE_ADDRESS_MASK: u32 = PAGE_SIZE - 1; let page = addr >> PAGE_ADDRESS_SIZE; let page_address = (addr & PAGE_ADDRESS_MASK) as usize; for (page_index, memory) in self.memory.iter() { @@ -371,14 +368,14 @@ impl Env { // Compute memory usage fn memory_usage(&self) -> String { - let total = self.memory.len() * PAGE_SIZE; + let total = self.memory.len() * PAGE_SIZE as usize; memory_size(total) } fn page_address(&self) -> (u32, usize) { let address = self.instruction_pointer; let page = address >> PAGE_ADDRESS_SIZE; - let page_address = (address & (PAGE_ADDRESS_MASK as u32)) as usize; + let page_address = (address & PAGE_ADDRESS_MASK) as usize; (page, page_address) } From c310c9c61b951ea8780e3bffdd82be1e0e0d3b63 Mon Sep 17 00:00:00 2001 From: Danny Willems Date: Fri, 1 Dec 2023 14:04:51 +0100 Subject: [PATCH 15/19] Fix lw instruction Also add fetch_memory. When constraining, it should be with RAMlookup. --- optimism/src/mips/interpreter.rs | 14 +++++++++++--- optimism/src/mips/witness.rs | 11 +++++++++++ 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/optimism/src/mips/interpreter.rs b/optimism/src/mips/interpreter.rs index 2d707286a0..820eba1cd5 100644 --- a/optimism/src/mips/interpreter.rs +++ b/optimism/src/mips/interpreter.rs @@ -1,5 +1,6 @@ use serde::{Deserialize, Serialize}; use std::ops::Index; +use log::debug; use strum_macros::{EnumCount, EnumIter}; pub const FD_STDIN: u32 = 0; @@ -204,6 +205,8 @@ pub trait InterpreterEnv { fn fetch_register_checked(&self, register_idx: &Self::Variable) -> Self::Variable; + fn fetch_memory(&mut self, addr: &Self::Variable) -> Self::Variable; + fn set_instruction_pointer(&mut self, ip: Self::Variable); fn get_immediate(&self) -> Self::Variable { @@ -339,9 +342,14 @@ pub fn interpret_itype(env: &mut Env, instr: ITypeInstructi ITypeInstruction::Load8 => (), ITypeInstruction::Load16 => (), ITypeInstruction::Load32 => { - let rt = env.get_instruction_part(InstructionPart::RT); - let immediate_value = env.get_immediate(); - env.overwrite_register_checked(&rt, &immediate_value); + let dest = env.get_instruction_part(InstructionPart::RT); + let addr = env.get_instruction_part(InstructionPart::RS); + let offset = env.get_immediate(); + let addr_with_offset = addr.clone() + offset.clone(); + debug!("lw {}, {}({})", dest.clone(), offset.clone(), addr.clone()); + let value = env.fetch_memory(&addr_with_offset); + debug!("Loaded value from {}: {}", addr_with_offset.clone(), value); + env.overwrite_register_checked(&dest, &value); env.set_instruction_pointer(env.get_instruction_pointer() + Env::constant(4u32)); // TODO: update next_instruction_pointer // REMOVEME: when all itype instructions are implemented. diff --git a/optimism/src/mips/witness.rs b/optimism/src/mips/witness.rs index 38255048e9..85ceb4feeb 100644 --- a/optimism/src/mips/witness.rs +++ b/optimism/src/mips/witness.rs @@ -116,6 +116,17 @@ impl InterpreterEnv for Env { self.instruction_parts[part] } + fn fetch_memory(&mut self, addr: &Self::Variable) -> Self::Variable { + let page = addr >> PAGE_ADDRESS_SIZE; + let page_address = (addr & PAGE_ADDRESS_MASK) as usize; + for (page_index, memory) in self.memory.iter() { + if *page_index == page { + return memory[page_address].into(); + } + } + panic!("Could not access address") + } + fn set_instruction_pointer(&mut self, ip: Self::Variable) { self.instruction_pointer = ip; // Set next instruction pointer? From c56a237defc52be94031c16c3e67cc3c2e64e631 Mon Sep 17 00:00:00 2001 From: Danny Willems Date: Fri, 1 Dec 2023 14:36:03 +0100 Subject: [PATCH 16/19] Formatting --- optimism/src/mips/interpreter.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/optimism/src/mips/interpreter.rs b/optimism/src/mips/interpreter.rs index 820eba1cd5..3ff526a980 100644 --- a/optimism/src/mips/interpreter.rs +++ b/optimism/src/mips/interpreter.rs @@ -466,7 +466,7 @@ mod tests { // We only care about instruction parts and instruction pointer let mut dummy_env = dummy_env(); // Instruction: 0b00111100000000010000000000001010 - // lui at,0xa + // lui at, 0xa dummy_env.instruction_parts = InstructionParts { op_code: 0b000010, rs: 0b00000, From 35236d68ead5b6e0a1b645a682fd9d53f0041c7c Mon Sep 17 00:00:00 2001 From: Danny Willems Date: Fri, 1 Dec 2023 15:35:10 +0100 Subject: [PATCH 17/19] Add rand dependency --- Cargo.lock | 1 + optimism/Cargo.toml | 1 + 2 files changed, 2 insertions(+) diff --git a/Cargo.lock b/Cargo.lock index 885f193826..da3a45e2fa 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1338,6 +1338,7 @@ dependencies = [ "mina-poseidon", "os_pipe", "poly-commitment", + "rand", "regex", "rmp-serde", "serde", diff --git a/optimism/Cargo.toml b/optimism/Cargo.toml index d8937dfd48..7627b373a7 100644 --- a/optimism/Cargo.toml +++ b/optimism/Cargo.toml @@ -37,3 +37,4 @@ log = "0.4.20" env_logger = "0.10.0" command-fds = "0.2.3" os_pipe = "1.1.4" +rand = "0.8.0" From 08a157f3e3027b8e537332089002999f4298f05f Mon Sep 17 00:00:00 2001 From: Danny Willems Date: Fri, 1 Dec 2023 15:35:52 +0100 Subject: [PATCH 18/19] Fix tests for lw --- optimism/src/mips/interpreter.rs | 43 ++++++++++++++++++++++++++------ 1 file changed, 35 insertions(+), 8 deletions(-) diff --git a/optimism/src/mips/interpreter.rs b/optimism/src/mips/interpreter.rs index 3ff526a980..57e279ac13 100644 --- a/optimism/src/mips/interpreter.rs +++ b/optimism/src/mips/interpreter.rs @@ -1,6 +1,6 @@ +use log::debug; use serde::{Deserialize, Serialize}; use std::ops::Index; -use log::debug; use strum_macros::{EnumCount, EnumIter}; pub const FD_STDIN: u32 = 0; @@ -347,8 +347,18 @@ pub fn interpret_itype(env: &mut Env, instr: ITypeInstructi let offset = env.get_immediate(); let addr_with_offset = addr.clone() + offset.clone(); debug!("lw {}, {}({})", dest.clone(), offset.clone(), addr.clone()); - let value = env.fetch_memory(&addr_with_offset); - debug!("Loaded value from {}: {}", addr_with_offset.clone(), value); + // We load 4 bytes, i.e. one word. + debug!("{}, {}({})", dest.clone(), offset.clone(), addr.clone()); + let v0 = env.fetch_memory(&addr_with_offset); + let v1 = env.fetch_memory(&(addr_with_offset.clone() + Env::constant(1))); + let v2 = env.fetch_memory(&(addr_with_offset.clone() + Env::constant(2))); + let v3 = env.fetch_memory(&(addr_with_offset.clone() + Env::constant(3))); + let value = (v0 << 24) + (v1 << 16) + (v2 << 8) + v3; + debug!( + "Loaded 32 bits value from {}: {}", + addr_with_offset.clone(), + value + ); env.overwrite_register_checked(&dest, &value); env.set_instruction_pointer(env.get_instruction_pointer() + Env::constant(4u32)); // TODO: update next_instruction_pointer @@ -374,22 +384,25 @@ pub fn interpret_itype(env: &mut Env, instr: ITypeInstructi mod tests { use super::*; - use crate::cannon::HostProgram; + use crate::cannon::{HostProgram, PAGE_SIZE}; use crate::mips::registers::Registers; use crate::mips::witness::{Env, SyscallEnv, SCRATCH_SIZE}; use crate::preimage_oracle::PreImageOracle; use mina_curves::pasta::Fp; + use rand::Rng; fn dummy_env() -> Env { let host_program = Some(HostProgram { name: String::from("true"), arguments: vec![], }); + let mut rng = rand::thread_rng(); let dummy_preimage_oracle = PreImageOracle::create(&host_program); Env { instruction_parts: InstructionParts::default(), instruction_counter: 0, - memory: vec![], + // Only 4kb of memory (one PAGE_ADDRESS_SIZE) + memory: vec![(0, vec![rng.gen(); PAGE_SIZE as usize])], memory_write_index: vec![], registers: Registers::default(), registers_write_index: Registers::default(), @@ -423,11 +436,25 @@ mod tests { #[test] fn test_unit_load32_instruction() { - // We only care about instruction parts and instruction pointer + let mut rng = rand::thread_rng(); + // lw instruction let mut dummy_env = dummy_env(); // Instruction: 0b10001111101001000000000000000000 - // lw $a0, 0 + // lw $a0, 0(29) // a0 = 4 + // Random address in SP + // Address has only one index + let addr: u32 = rng.gen_range(0u32..100u32); + let aligned_addr: u32 = (addr / 4) * 4; + dummy_env.registers[REGISTER_SP as usize] = aligned_addr; + let mem = dummy_env.memory[0].clone(); + let mem = mem.1; + let v0 = mem[aligned_addr as usize]; + let v1 = mem[(aligned_addr + 1) as usize]; + let v2 = mem[(aligned_addr + 2) as usize]; + let v3 = mem[(aligned_addr + 3) as usize]; + let exp_v = ((v0 as u32) << 24) + ((v1 as u32) << 16) + ((v2 as u32) << 8) + (v3 as u32); + // Set random alue into registers dummy_env.instruction_parts = InstructionParts { op_code: 0b000010, rs: 0b11101, @@ -437,7 +464,7 @@ mod tests { funct: 0b000000, }; interpret_itype(&mut dummy_env, ITypeInstruction::Load32); - assert_eq!(dummy_env.registers[REGISTER_A0 as usize], 0); + assert_eq!(dummy_env.registers[REGISTER_A0 as usize], exp_v); } #[test] From 1e1feedc41da8a25940682964ebd14b4303a64b7 Mon Sep 17 00:00:00 2001 From: Danny Willems Date: Fri, 1 Dec 2023 18:17:38 +0100 Subject: [PATCH 19/19] Update optimism/src/mips/interpreter.rs --- optimism/src/mips/interpreter.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/optimism/src/mips/interpreter.rs b/optimism/src/mips/interpreter.rs index 57e279ac13..b153e32f5f 100644 --- a/optimism/src/mips/interpreter.rs +++ b/optimism/src/mips/interpreter.rs @@ -348,7 +348,6 @@ pub fn interpret_itype(env: &mut Env, instr: ITypeInstructi let addr_with_offset = addr.clone() + offset.clone(); debug!("lw {}, {}({})", dest.clone(), offset.clone(), addr.clone()); // We load 4 bytes, i.e. one word. - debug!("{}, {}({})", dest.clone(), offset.clone(), addr.clone()); let v0 = env.fetch_memory(&addr_with_offset); let v1 = env.fetch_memory(&(addr_with_offset.clone() + Env::constant(1))); let v2 = env.fetch_memory(&(addr_with_offset.clone() + Env::constant(2)));