From 75ad4f161ce10f05fae217a41e70454f29530163 Mon Sep 17 00:00:00 2001 From: thealmarty <“thealmartyblog@gmail.com”> Date: Fri, 26 Apr 2024 08:49:38 -0700 Subject: [PATCH 1/2] Add tloadu8 instruction. --- assembler/grammar/assembly.pest | 2 +- assembler/src/lib.rs | 3 +- basic/src/lib.rs | 6 ++- cpu/src/columns.rs | 1 + cpu/src/lib.rs | 72 ++++++++++++++++++++++++++++++++- machine/src/program.rs | 3 ++ opcodes/src/lib.rs | 2 + 7 files changed, 84 insertions(+), 5 deletions(-) diff --git a/assembler/grammar/assembly.pest b/assembler/grammar/assembly.pest index 82cea9e..2265213 100644 --- a/assembler/grammar/assembly.pest +++ b/assembler/grammar/assembly.pest @@ -3,7 +3,7 @@ comment = { ";" ~ (!"\n" ~ ANY)* ~ "\n" } label = { (!":" ~ !"\n" ~ ANY)+ ~ ":" ~ "\n" } instruction = { mnemonic ~ (operand ~ ", "?)+? ~ "\n"? } mnemonic = { - "lw" | "sw" | "loadu8" | "loads8" | "storeu8" | "jalv" | "jal" | "beqi" | "beq" | "bnei" | "bne" | "imm32" | "stop" | + "lw" | "sw" | "loadu8" | "tloadu8" | "loads8" | "storeu8" | "jalv" | "jal" | "beqi" | "beq" | "bnei" | "bne" | "imm32" | "stop" | "advread" | "advwrite" | "addi" | "add" | "subi" | "sub" | "muli" | "mul" | "mulhsi"| "mulhui"| "mulhs"| "mulhu" | "divi" | "div" | "sdiv" | "sdivi" | "ilte" | "ltei" | "lte" | "ilt" | "lti" | "lt" | "shli" | "shl" | "shri" | "shr" | "srai" | "sra" | diff --git a/assembler/src/lib.rs b/assembler/src/lib.rs index b3ed64b..7b5e8cf 100644 --- a/assembler/src/lib.rs +++ b/assembler/src/lib.rs @@ -59,6 +59,7 @@ pub fn assemble(input: &str) -> Result, String> { // Core CPU "lw" => LOAD32, "loadu8" => LOADU8, + "tloadu8" => TLOADU8, "loads8" => LOADS8, "sw" => STORE32, "storeu8" => STOREU8, @@ -104,7 +105,7 @@ pub fn assemble(input: &str) -> Result, String> { // Insert zero operands if necessary match mnemonic { - "lw" | "loadu8" | "loads8" => { + "lw" | "loadu8"| "tloadu8" | "loads8" => { // (a, 0, c, 0, 0) operands.insert(1, 0); operands.extend(vec![0; 2]); diff --git a/basic/src/lib.rs b/basic/src/lib.rs index 29aef54..aaff25b 100644 --- a/basic/src/lib.rs +++ b/basic/src/lib.rs @@ -40,7 +40,7 @@ use valida_bus::{ }; use valida_cpu::{ BeqInstruction, BneInstruction, Imm32Instruction, JalInstruction, JalvInstruction, - Load32Instruction, LoadFpInstruction, LoadS8Instruction, LoadU8Instruction, + Load32Instruction, LoadFpInstruction, LoadS8Instruction, LoadU8Instruction, TLoadU8Instruction, ReadAdviceInstruction, StopInstruction, Store32Instruction, StoreU8Instruction, }; use valida_cpu::{CpuChip, MachineWithCpuChip}; @@ -67,6 +67,7 @@ pub struct BasicMachine { // Core instructions load32: Load32Instruction, loadu8: LoadU8Instruction, + tloadu8: TLoadU8Instruction, loads8: LoadS8Instruction, store32: Store32Instruction, storeu8: StoreU8Instruction, @@ -1081,6 +1082,9 @@ impl Machine for BasicMachine { >::OPCODE => { LoadU8Instruction::execute_with_advice::(self, ops, advice) } + >::OPCODE => { + TLoadU8Instruction::execute_with_advice::(self, ops, advice) + } >::OPCODE => { LoadS8Instruction::execute_with_advice::(self, ops, advice) } diff --git a/cpu/src/columns.rs b/cpu/src/columns.rs index 589cb99..0c8333c 100644 --- a/cpu/src/columns.rs +++ b/cpu/src/columns.rs @@ -49,6 +49,7 @@ pub struct OpcodeFlagCols { pub is_imm_op: T, pub is_load: T, pub is_load_u8: T, + pub is_tload_u8: T, pub is_load_s8: T, pub is_store: T, pub is_store_u8: T, diff --git a/cpu/src/lib.rs b/cpu/src/lib.rs index 424affc..8134ecf 100644 --- a/cpu/src/lib.rs +++ b/cpu/src/lib.rs @@ -17,7 +17,7 @@ use valida_machine::{ }; use valida_memory::{MachineWithMemoryChip, Operation as MemoryOperation}; use valida_opcodes::{ - BEQ, BNE, BYTES_PER_INSTR, IMM32, JAL, JALV, LOAD32, LOADFP, LOADS8, LOADU8, READ_ADVICE, STOP, + BEQ, BNE, BYTES_PER_INSTR, IMM32, JAL, JALV, LOAD32, LOADFP, LOADS8, LOADU8, TLOADU8, READ_ADVICE, STOP, STORE32, STOREU8, }; @@ -37,6 +37,7 @@ pub enum Operation { StoreU8, Load32, LoadU8, + TLoadU8, LoadS8, Jal, Jalv, @@ -187,6 +188,9 @@ impl CpuChip { Operation::LoadU8 => { cols.opcode_flags.is_load_u8 = SC::Val::one(); } + Operation::TLoadU8 => { + cols.opcode_flags.is_tload_u8 = SC::Val::one(); + } Operation::LoadS8 => { cols.opcode_flags.is_load_s8 = SC::Val::one(); } @@ -365,6 +369,7 @@ pub trait MachineWithCpuChip: MachineWithMemoryChip { instructions!( Load32Instruction, LoadU8Instruction, + TLoadU8Instruction, LoadS8Instruction, Store32Instruction, StoreU8Instruction, @@ -475,6 +480,70 @@ where } } + +impl Instruction for TLoadU8Instruction +where + M: MachineWithCpuChip, + F: Field, +{ + const OPCODE: u32 = TLOADU8; + + fn execute(state: &mut M, ops: Operands) { + let opcode = >::OPCODE; + let clk = state.cpu().clock; + let pc = state.cpu().pc; + let fp = state.cpu().fp; + + let read_addr_loc = (fp as i32 + ops.c()) as u32; + + let read_addr = state + .mem_mut() + .read(clk, read_addr_loc, true, pc, opcode, 0, ""); + let read_addr_index = addr_of_word(read_addr.into()); + + // The word from the read address. + let cell = state.mem_mut().read( + clk, + read_addr_index, + true, + pc, + opcode, + 1, + &format!( + "fp = {}, c = {}, [fp+c] = {:?}", + fp as i32, + ops.c() as u32, + read_addr_index + ), + ); + + // The array index of the word for the byte to read from + let index_of_read = index_of_byte(read_addr.into()); + // The byte from the read cell. + let cell_byte: u8 = cell[index_of_read]; + + let write_addr = (state.cpu().fp as i32 + ops.a()) as u32; + // The address, converted to a multiple of 4. + let write_addr_index = addr_of_word(write_addr); + + // The array index of the word for the byte to write to + let index_of_write = index_of_byte(write_addr); + + // The original content of the cell to write to. If the cell is empty, initiate it with a default value. + let cell_write = state.mem_mut().read_or_init(clk, write_addr_index, true); + + // The Word to write, with one byte overwritten to the read byte + let cell_to_write = cell_write.update_byte(cell_byte, index_of_write); + + state + .mem_mut() + .write(clk, write_addr_index, cell_to_write, true); + state.cpu_mut().pc += 1; + state.cpu_mut().push_op(Operation::TLoadU8, opcode, ops); + } +} + + impl Instruction for LoadU8Instruction where M: MachineWithCpuChip, @@ -520,7 +589,6 @@ where // The address, converted to a multiple of 4. let write_addr_index = addr_of_word(write_addr); - // The Word to write, with one byte overwritten to the read byte state .mem_mut() .write(clk, write_addr_index, Word::from_u8(cell_byte), true); diff --git a/machine/src/program.rs b/machine/src/program.rs index 3032f8c..5872ac2 100644 --- a/machine/src/program.rs +++ b/machine/src/program.rs @@ -105,6 +105,9 @@ impl InstructionWord { valida_opcodes::LOADU8 => { format!("{}(fp), {}(fp)", self.operands.0[0], self.operands.0[2]) } + valida_opcodes::TLOADU8 => { + format!("{}(fp), {}(fp)", self.operands.0[0], self.operands.0[2]) + } valida_opcodes::LOADS8 => { format!("{}(fp), {}(fp)", self.operands.0[0], self.operands.0[2]) } diff --git a/opcodes/src/lib.rs b/opcodes/src/lib.rs index fee6411..f91af9d 100644 --- a/opcodes/src/lib.rs +++ b/opcodes/src/lib.rs @@ -18,6 +18,7 @@ pub enum Opcode { LOADU8 = 11, LOADS8 = 12, STOREU8 = 13, + TLOADU8 = 16, ADD32 = 100, SUB32 = 101, @@ -65,6 +66,7 @@ declare_opcode!(LOADFP); declare_opcode!(LOADU8); declare_opcode!(LOADS8); declare_opcode!(STOREU8); +declare_opcode!(TLOADU8); /// NONDETERMINISTIC declare_opcode!(READ_ADVICE); From 953300c89967dc1cc181b7a37ac5b27a47c2a780 Mon Sep 17 00:00:00 2001 From: thealmarty <“thealmartyblog@gmail.com”> Date: Fri, 26 Apr 2024 10:58:24 -0700 Subject: [PATCH 2/2] Fix comments. --- assembler/src/lib.rs | 2 +- basic/src/lib.rs | 3 ++- cpu/src/lib.rs | 10 ++++------ machine/src/core.rs | 3 ++- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/assembler/src/lib.rs b/assembler/src/lib.rs index 7b5e8cf..5154c9a 100644 --- a/assembler/src/lib.rs +++ b/assembler/src/lib.rs @@ -105,7 +105,7 @@ pub fn assemble(input: &str) -> Result, String> { // Insert zero operands if necessary match mnemonic { - "lw" | "loadu8"| "tloadu8" | "loads8" => { + "lw" | "loadu8" | "tloadu8" | "loads8" => { // (a, 0, c, 0, 0) operands.insert(1, 0); operands.extend(vec![0; 2]); diff --git a/basic/src/lib.rs b/basic/src/lib.rs index aaff25b..8b5e333 100644 --- a/basic/src/lib.rs +++ b/basic/src/lib.rs @@ -40,8 +40,9 @@ use valida_bus::{ }; use valida_cpu::{ BeqInstruction, BneInstruction, Imm32Instruction, JalInstruction, JalvInstruction, - Load32Instruction, LoadFpInstruction, LoadS8Instruction, LoadU8Instruction, TLoadU8Instruction, + Load32Instruction, LoadFpInstruction, LoadS8Instruction, LoadU8Instruction, ReadAdviceInstruction, StopInstruction, Store32Instruction, StoreU8Instruction, + TLoadU8Instruction, }; use valida_cpu::{CpuChip, MachineWithCpuChip}; use valida_machine::__internal::p3_challenger::{CanObserve, FieldChallenger}; diff --git a/cpu/src/lib.rs b/cpu/src/lib.rs index 8134ecf..b65d612 100644 --- a/cpu/src/lib.rs +++ b/cpu/src/lib.rs @@ -17,8 +17,8 @@ use valida_machine::{ }; use valida_memory::{MachineWithMemoryChip, Operation as MemoryOperation}; use valida_opcodes::{ - BEQ, BNE, BYTES_PER_INSTR, IMM32, JAL, JALV, LOAD32, LOADFP, LOADS8, LOADU8, TLOADU8, READ_ADVICE, STOP, - STORE32, STOREU8, + BEQ, BNE, BYTES_PER_INSTR, IMM32, JAL, JALV, LOAD32, LOADFP, LOADS8, LOADU8, READ_ADVICE, STOP, + STORE32, STOREU8, TLOADU8, }; use p3_air::VirtualPairCol; @@ -480,7 +480,6 @@ where } } - impl Instruction for TLoadU8Instruction where M: MachineWithCpuChip, @@ -534,7 +533,7 @@ where // The Word to write, with one byte overwritten to the read byte let cell_to_write = cell_write.update_byte(cell_byte, index_of_write); - + state .mem_mut() .write(clk, write_addr_index, cell_to_write, true); @@ -543,7 +542,6 @@ where } } - impl Instruction for LoadU8Instruction where M: MachineWithCpuChip, @@ -643,7 +641,7 @@ where // The address, converted to a multiple of 4. let write_addr_index = addr_of_word(write_addr); - // The Word to write, with one byte overwritten to the read byte + // The Word to write, with the read byte sign extended to 32 bits. let cell_to_write = Word::sign_extend_byte(cell_byte); state diff --git a/machine/src/core.rs b/machine/src/core.rs index c0c2597..2df2038 100644 --- a/machine/src/core.rs +++ b/machine/src/core.rs @@ -42,7 +42,8 @@ impl Word { } } -// The cell is stored in little endian format in the compiler. But the VM stores it in big endian. +/// Update the cell with one byte overwritten to the input byte. +/// The cell is stored in little endian format in the compiler. But the VM stores it in big endian. impl Word { pub fn update_byte(self, byte: u8, loc: usize) -> Self { let result_little_end: [u8; MEMORY_CELL_BYTES] = self.0;