diff --git a/.gitignore b/.gitignore index 3a29d80589..5302249431 100644 --- a/.gitignore +++ b/.gitignore @@ -25,4 +25,13 @@ _build *.html # If symlink created for kimchi-visu -tools/srs \ No newline at end of file +tools/srs + +optimism/*op-program-data-log.sh +optimism/cpu.pprof +optimism/meta.json +optimism/out.json +optimism/op-program-db* +optimism/state.json +meta.json +state.json diff --git a/optimism/run-vm.sh b/optimism/run-vm.sh index 4f24506b4e..a1bb042c3b 100755 --- a/optimism/run-vm.sh +++ b/optimism/run-vm.sh @@ -1,7 +1,7 @@ #!/usr/bin/env bash set -euo pipefail -cargo run -p kimchi_optimism -- \ +cargo run --release -p kimchi_optimism -- \ --pprof-cpu \ --info-at '%10000000' \ --proof-at never \ diff --git a/optimism/src/mips/interpreter.rs b/optimism/src/mips/interpreter.rs index 8ac18a104b..2180c5f711 100644 --- a/optimism/src/mips/interpreter.rs +++ b/optimism/src/mips/interpreter.rs @@ -1,3 +1,5 @@ +use serde::{Deserialize, Serialize}; +use std::ops::Index; use strum_macros::{EnumCount, EnumIter}; pub const FD_STDIN: u32 = 0; @@ -8,6 +10,42 @@ pub const FD_HINT_WRITE: u32 = 4; pub const FD_PREIMAGE_READ: u32 = 5; pub const FD_PREIMAGE_WRITE: u32 = 6; +#[derive(Debug, Clone, Copy, Eq, PartialEq, EnumCount, EnumIter)] +pub enum InstructionPart { + OpCode, + RS, + RT, + RD, + Shamt, + Funct, +} + +#[derive(Debug, Clone, Copy, Eq, PartialEq, Default, Serialize, Deserialize)] +pub struct InstructionParts { + pub op_code: T, + pub rs: T, + pub rt: T, + pub rd: T, + pub shamt: T, + pub funct: T, +} + +// To use InstructionParts[OpCode] +impl Index for InstructionParts { + type Output = A; + + fn index(&self, index: InstructionPart) -> &Self::Output { + match index { + InstructionPart::OpCode => &self.op_code, + InstructionPart::RS => &self.rs, + InstructionPart::RT => &self.rt, + InstructionPart::RD => &self.rd, + InstructionPart::Shamt => &self.shamt, + InstructionPart::Funct => &self.funct, + } + } +} + #[derive(Debug, Clone, Copy, Eq, PartialEq)] pub enum Instruction { RType(RTypeInstruction), diff --git a/optimism/src/mips/witness.rs b/optimism/src/mips/witness.rs index 8ab5d93433..db2d6cacf5 100644 --- a/optimism/src/mips/witness.rs +++ b/optimism/src/mips/witness.rs @@ -5,7 +5,8 @@ use crate::{ }, mips::{ interpreter::{ - self, ITypeInstruction, Instruction, InterpreterEnv, JTypeInstruction, RTypeInstruction, + self, ITypeInstruction, Instruction, InstructionParts, InterpreterEnv, + JTypeInstruction, RTypeInstruction, }, registers::Registers, }, @@ -42,6 +43,7 @@ impl SyscallEnv { } pub struct Env { + pub instruction_parts: InstructionParts, pub instruction_counter: usize, pub memory: Vec<(u32, Vec)>, pub memory_write_index: Vec<(u32, Vec)>, @@ -144,6 +146,9 @@ impl Env { }; Env { + // Will be modified by decode_instruction. + // We set the instruction parts to 0 to begin + instruction_parts: InstructionParts::default(), instruction_counter: state.step as usize, memory: initial_memory.clone(), memory_write_index: memory_offsets @@ -176,122 +181,135 @@ impl Env { panic!("Could not access address") } - pub fn decode_instruction(&self) -> Instruction { + 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); - match instruction >> 26 { - 0x00 => match instruction & 0x3F { - 0x00 => Instruction::RType(RTypeInstruction::ShiftLeftLogical), - 0x02 => Instruction::RType(RTypeInstruction::ShiftRightLogical), - 0x03 => Instruction::RType(RTypeInstruction::ShiftRightArithmetic), - 0x04 => Instruction::RType(RTypeInstruction::ShiftLeftLogicalVariable), - 0x06 => Instruction::RType(RTypeInstruction::ShiftRightLogicalVariable), - 0x07 => Instruction::RType(RTypeInstruction::ShiftRightArithmeticVariable), - 0x08 => Instruction::RType(RTypeInstruction::JumpRegister), - 0x09 => Instruction::RType(RTypeInstruction::JumpAndLinkRegister), - 0x0a => Instruction::RType(RTypeInstruction::MoveZero), - 0x0b => Instruction::RType(RTypeInstruction::MoveNonZero), - 0x0c => match self.registers.general_purpose[2] { - 4090 => Instruction::RType(RTypeInstruction::SyscallMmap), - 4045 => { - // sysBrk - Instruction::RType(RTypeInstruction::SyscallOther) - } - 4120 => { - // sysClone - Instruction::RType(RTypeInstruction::SyscallOther) - } - 4246 => Instruction::RType(RTypeInstruction::SyscallExitGroup), - 4003 => match self.registers.general_purpose[4] { - interpreter::FD_PREIMAGE_READ => { - Instruction::RType(RTypeInstruction::SyscallReadPreimage) + let opcode = { + match instruction >> 26 { + 0x00 => match instruction & 0x3F { + 0x00 => Instruction::RType(RTypeInstruction::ShiftLeftLogical), + 0x02 => Instruction::RType(RTypeInstruction::ShiftRightLogical), + 0x03 => Instruction::RType(RTypeInstruction::ShiftRightArithmetic), + 0x04 => Instruction::RType(RTypeInstruction::ShiftLeftLogicalVariable), + 0x06 => Instruction::RType(RTypeInstruction::ShiftRightLogicalVariable), + 0x07 => Instruction::RType(RTypeInstruction::ShiftRightArithmeticVariable), + 0x08 => Instruction::RType(RTypeInstruction::JumpRegister), + 0x09 => Instruction::RType(RTypeInstruction::JumpAndLinkRegister), + 0x0a => Instruction::RType(RTypeInstruction::MoveZero), + 0x0b => Instruction::RType(RTypeInstruction::MoveNonZero), + 0x0c => match self.registers.general_purpose[2] { + 4090 => Instruction::RType(RTypeInstruction::SyscallMmap), + 4045 => { + // sysBrk + Instruction::RType(RTypeInstruction::SyscallOther) } - _ => Instruction::RType(RTypeInstruction::SyscallReadOther), - }, - 4004 => match self.registers.general_purpose[4] { - interpreter::FD_PREIMAGE_WRITE => { - Instruction::RType(RTypeInstruction::SyscallWritePreimage) + 4120 => { + // sysClone + Instruction::RType(RTypeInstruction::SyscallOther) } - interpreter::FD_HINT_WRITE => { - Instruction::RType(RTypeInstruction::SyscallWriteHint) + 4246 => Instruction::RType(RTypeInstruction::SyscallExitGroup), + 4003 => match self.registers.general_purpose[4] { + interpreter::FD_PREIMAGE_READ => { + Instruction::RType(RTypeInstruction::SyscallReadPreimage) + } + _ => Instruction::RType(RTypeInstruction::SyscallReadOther), + }, + 4004 => match self.registers.general_purpose[4] { + interpreter::FD_PREIMAGE_WRITE => { + Instruction::RType(RTypeInstruction::SyscallWritePreimage) + } + interpreter::FD_HINT_WRITE => { + Instruction::RType(RTypeInstruction::SyscallWriteHint) + } + _ => Instruction::RType(RTypeInstruction::SyscallWriteOther), + }, + 4055 => Instruction::RType(RTypeInstruction::SyscallFcntl), + _ => { + // NB: This has well-defined behavior. Don't panic! + Instruction::RType(RTypeInstruction::SyscallOther) } - _ => Instruction::RType(RTypeInstruction::SyscallWriteOther), }, - 4055 => Instruction::RType(RTypeInstruction::SyscallFcntl), + 0x0f => Instruction::RType(RTypeInstruction::Sync), + 0x10 => Instruction::RType(RTypeInstruction::MoveFromHi), + 0x11 => Instruction::RType(RTypeInstruction::MoveToHi), + 0x12 => Instruction::RType(RTypeInstruction::MoveFromLo), + 0x13 => Instruction::RType(RTypeInstruction::MoveToLo), + 0x18 => Instruction::RType(RTypeInstruction::Multiply), + 0x19 => Instruction::RType(RTypeInstruction::MultiplyUnsigned), + 0x1a => Instruction::RType(RTypeInstruction::Div), + 0x1b => Instruction::RType(RTypeInstruction::DivUnsigned), + 0x20 => Instruction::RType(RTypeInstruction::Add), + 0x21 => Instruction::RType(RTypeInstruction::AddUnsigned), + 0x22 => Instruction::RType(RTypeInstruction::Sub), + 0x23 => Instruction::RType(RTypeInstruction::SubUnsigned), + 0x24 => Instruction::RType(RTypeInstruction::And), + 0x25 => Instruction::RType(RTypeInstruction::Or), + 0x26 => Instruction::RType(RTypeInstruction::Xor), + 0x2a => Instruction::RType(RTypeInstruction::SetLessThan), + 0x2b => Instruction::RType(RTypeInstruction::SetLessThanUnsigned), _ => { - // NB: This has well-defined behavior. Don't panic! - Instruction::RType(RTypeInstruction::SyscallOther) + panic!("Unhandled instruction {:#X}", instruction) } }, - 0x0f => Instruction::RType(RTypeInstruction::Sync), - 0x10 => Instruction::RType(RTypeInstruction::MoveFromHi), - 0x11 => Instruction::RType(RTypeInstruction::MoveToHi), - 0x12 => Instruction::RType(RTypeInstruction::MoveFromLo), - 0x13 => Instruction::RType(RTypeInstruction::MoveToLo), - 0x18 => Instruction::RType(RTypeInstruction::Multiply), - 0x19 => Instruction::RType(RTypeInstruction::MultiplyUnsigned), - 0x1a => Instruction::RType(RTypeInstruction::Div), - 0x1b => Instruction::RType(RTypeInstruction::DivUnsigned), - 0x20 => Instruction::RType(RTypeInstruction::Add), - 0x21 => Instruction::RType(RTypeInstruction::AddUnsigned), - 0x22 => Instruction::RType(RTypeInstruction::Sub), - 0x23 => Instruction::RType(RTypeInstruction::SubUnsigned), - 0x24 => Instruction::RType(RTypeInstruction::And), - 0x25 => Instruction::RType(RTypeInstruction::Or), - 0x26 => Instruction::RType(RTypeInstruction::Xor), - 0x2a => Instruction::RType(RTypeInstruction::SetLessThan), - 0x2b => Instruction::RType(RTypeInstruction::SetLessThanUnsigned), + 0x02 => Instruction::JType(JTypeInstruction::Jump), + 0x03 => Instruction::JType(JTypeInstruction::JumpAndLink), + 0x08 => Instruction::IType(ITypeInstruction::AddImmediate), + 0x09 => Instruction::IType(ITypeInstruction::AddImmediateUnsigned), + 0x0A => Instruction::IType(ITypeInstruction::SetLessThanImmediate), + 0x0B => Instruction::IType(ITypeInstruction::SetLessThanImmediateUnsigned), + 0x0C => Instruction::IType(ITypeInstruction::AndImmediate), + 0x0D => Instruction::IType(ITypeInstruction::OrImmediate), + 0x0E => Instruction::IType(ITypeInstruction::XorImmediate), + 0x0F => Instruction::IType(ITypeInstruction::LoadUpperImmediate), + 0x1C => match instruction & 0x3F { + 0x02 => Instruction::RType(RTypeInstruction::MultiplyToRegister), + 0x20 => Instruction::RType(RTypeInstruction::CountLeadingZeros), + 0x21 => Instruction::RType(RTypeInstruction::CountLeadingOnes), + _ => panic!("Unhandled instruction {:#X}", instruction), + }, + 0x20 => Instruction::IType(ITypeInstruction::Load8), + 0x21 => Instruction::IType(ITypeInstruction::Load16), + 0x22 => Instruction::IType(ITypeInstruction::LoadWordLeft), + 0x23 => Instruction::IType(ITypeInstruction::Load32), + 0x24 => Instruction::IType(ITypeInstruction::Load8Unsigned), + 0x25 => Instruction::IType(ITypeInstruction::Load16Unsigned), + 0x26 => Instruction::IType(ITypeInstruction::LoadWordRight), + 0x28 => Instruction::IType(ITypeInstruction::Store8), + 0x29 => Instruction::IType(ITypeInstruction::Store16), + 0x2a => Instruction::IType(ITypeInstruction::StoreWordLeft), + 0x2b => Instruction::IType(ITypeInstruction::Store32), + 0x2e => Instruction::IType(ITypeInstruction::StoreWordRight), + 0x30 => { + // Note: This is ll (LoadLinked), but we're only simulating a single processor. + Instruction::IType(ITypeInstruction::Load32) + } + 0x38 => { + // Note: This is sc (StoreConditional), but we're only simulating a single processor. + Instruction::IType(ITypeInstruction::Store32) + } _ => { panic!("Unhandled instruction {:#X}", instruction) } - }, - 0x02 => Instruction::JType(JTypeInstruction::Jump), - 0x03 => Instruction::JType(JTypeInstruction::JumpAndLink), - 0x08 => Instruction::IType(ITypeInstruction::AddImmediate), - 0x09 => Instruction::IType(ITypeInstruction::AddImmediateUnsigned), - 0x0A => Instruction::IType(ITypeInstruction::SetLessThanImmediate), - 0x0B => Instruction::IType(ITypeInstruction::SetLessThanImmediateUnsigned), - 0x0C => Instruction::IType(ITypeInstruction::AndImmediate), - 0x0D => Instruction::IType(ITypeInstruction::OrImmediate), - 0x0E => Instruction::IType(ITypeInstruction::XorImmediate), - 0x0F => Instruction::IType(ITypeInstruction::LoadUpperImmediate), - 0x1C => match instruction & 0x3F { - 0x02 => Instruction::RType(RTypeInstruction::MultiplyToRegister), - 0x20 => Instruction::RType(RTypeInstruction::CountLeadingZeros), - 0x21 => Instruction::RType(RTypeInstruction::CountLeadingOnes), - _ => panic!("Unhandled instruction {:#X}", instruction), - }, - 0x20 => Instruction::IType(ITypeInstruction::Load8), - 0x21 => Instruction::IType(ITypeInstruction::Load16), - 0x22 => Instruction::IType(ITypeInstruction::LoadWordLeft), - 0x23 => Instruction::IType(ITypeInstruction::Load32), - 0x24 => Instruction::IType(ITypeInstruction::Load8Unsigned), - 0x25 => Instruction::IType(ITypeInstruction::Load16Unsigned), - 0x26 => Instruction::IType(ITypeInstruction::LoadWordRight), - 0x28 => Instruction::IType(ITypeInstruction::Store8), - 0x29 => Instruction::IType(ITypeInstruction::Store16), - 0x2a => Instruction::IType(ITypeInstruction::StoreWordLeft), - 0x2b => Instruction::IType(ITypeInstruction::Store32), - 0x2e => Instruction::IType(ITypeInstruction::StoreWordRight), - 0x30 => { - // Note: This is ll (LoadLinked), but we're only simulating a single processor. - Instruction::IType(ITypeInstruction::Load32) } - 0x38 => { - // Note: This is sc (StoreConditional), but we're only simulating a single processor. - Instruction::IType(ITypeInstruction::Store32) - } - _ => { - panic!("Unhandled instruction {:#X}", instruction) - } - } + }; + (opcode, instruction) } pub fn step(&mut self, config: VmConfiguration, metadata: &Meta, start: &Start) { - let instruction = self.decode_instruction(); - println!("instruction: {:?}", instruction); + let (opcode, instruction) = self.decode_instruction(); + 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)), + }; + self.instruction_parts = instruction_parts; + + println!("instruction: {:?}", opcode); self.pp_info(config.info_at, metadata, start); @@ -301,7 +319,7 @@ impl Env { return; } - interpreter::interpret_instruction(self, instruction); + interpreter::interpret_instruction(self, opcode); } fn should_trigger_at(&self, at: StepFrequency) -> bool { @@ -361,7 +379,7 @@ impl Env { .unwrap_or_else(|| "n/a".to_string()); info!( - "processing step {} pc {:#010x} insn {:#010x} ips {:.2} page {} mem {} name {}", + "processing step={} pc={:#010x} insn={:#010x} ips={:.2} page={} mem={} name={}", step, pc, insn, ips, pages, mem, name ); }