From 4298e18fc8047c2964933925ae5e7bcc882d59b8 Mon Sep 17 00:00:00 2001 From: Neelay Sant Date: Tue, 4 Feb 2025 11:21:55 +0000 Subject: [PATCH 1/2] RISC-V: Deduplicate Add OpCode and lower Add to JIT --- src/riscv/lib/src/interpreter.rs | 1 + src/riscv/lib/src/interpreter/i.rs | 57 +++++++++++++++++ src/riscv/lib/src/interpreter/rv32i.rs | 35 +--------- src/riscv/lib/src/jit.rs | 64 +++++++++++++++++++ src/riscv/lib/src/machine_state.rs | 4 +- .../lib/src/machine_state/block_cache.rs | 6 +- .../lib/src/machine_state/instruction.rs | 19 ++++-- .../machine_state/instruction/constructors.rs | 46 ++++++++++++- .../instruction/tagged_instruction.rs | 16 ++--- src/riscv/lib/src/parser.rs | 14 +++- src/riscv/lib/src/parser/instruction.rs | 3 + .../lib/tests/expected/jstz/state_hash_final | 2 +- 12 files changed, 210 insertions(+), 57 deletions(-) create mode 100644 src/riscv/lib/src/interpreter/i.rs diff --git a/src/riscv/lib/src/interpreter.rs b/src/riscv/lib/src/interpreter.rs index 28bf43e8b4ca..a7a08ffa41fa 100644 --- a/src/riscv/lib/src/interpreter.rs +++ b/src/riscv/lib/src/interpreter.rs @@ -7,6 +7,7 @@ mod atomics; pub mod c; mod common_memory; pub mod float; +pub mod i; pub mod rv32a; pub mod rv32c; pub mod rv32i; diff --git a/src/riscv/lib/src/interpreter/i.rs b/src/riscv/lib/src/interpreter/i.rs new file mode 100644 index 000000000000..34bce6a7d0f3 --- /dev/null +++ b/src/riscv/lib/src/interpreter/i.rs @@ -0,0 +1,57 @@ +// SPDX-FileCopyrightText: 2025 TriliTech +// +// SPDX-License-Identifier: MIT + +//! Implementation of Risc-V's 32 & 64 bit I extensions for RISC-V +//! +//! Chapter 5,1 - Unprivileged spec + +use crate::{instruction_context::ICB, machine_state::registers::NonZeroXRegister}; + +/// Perform val(rs1) + val(rs2) and store the result in `rd` +/// +/// Relevant RISC-V opcodes: +/// - ADD +/// - C.ADD +pub fn run_add( + icb: &mut impl ICB, + rs1: NonZeroXRegister, + rs2: NonZeroXRegister, + rd: NonZeroXRegister, +) { + let lhs = icb.xregister_read(rs1); + let rhs = icb.xregister_read(rs2); + // Wrapped addition in two's complement behaves the same for signed and unsigned + let result = icb.xvalue_wrapping_add(lhs, rhs); + icb.xregister_write(rd, result) +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::machine_state::MachineCoreState; + use crate::{ + backend_test, create_state, + machine_state::{main_memory::tests::T1K, registers::nz, MachineCoreStateLayout}, + }; + backend_test!(test_add, F, { + let imm_rs1_res = [ + (0_i64, 0_u64, 0_u64), + (0, 0xFFF0_0420, 0xFFF0_0420), + (-1, 0, 0xFFFF_FFFF_FFFF_FFFF), + (1_000_000, -123_000_987_i64 as u64, -122_000_987_i64 as u64), + (1_000_000, 123_000_987, 124_000_987), + (-1, -321_000_000_000_i64 as u64, -321_000_000_001_i64 as u64), + ]; + + for (imm, rs1, res) in imm_rs1_res { + let mut state = create_state!(MachineCoreState, MachineCoreStateLayout, F, T1K); + + state.hart.xregisters.write_nz(nz::a0, rs1); + state.hart.xregisters.write_nz(nz::t0, imm as u64); + + run_add(&mut state, nz::a0, nz::t0, nz::a0); + assert_eq!(state.hart.xregisters.read_nz(nz::a0), res); + } + }); +} diff --git a/src/riscv/lib/src/interpreter/rv32i.rs b/src/riscv/lib/src/interpreter/rv32i.rs index 5dddd231f661..eac17756e78c 100644 --- a/src/riscv/lib/src/interpreter/rv32i.rs +++ b/src/riscv/lib/src/interpreter/rv32i.rs @@ -34,17 +34,6 @@ where self.write(rd, result) } - /// `ADD` R-type instruction - /// - /// Perform val(rs1) + val(rs2) and store the result in `rd` - pub fn run_add(&mut self, rs1: XRegister, rs2: XRegister, rd: NonZeroXRegister) { - let lhs = self.read(rs1); - let rhs = self.read(rs2); - // Wrapped addition in two's complement behaves the same for signed and unsigned - let result = lhs.wrapping_add(rhs); - self.write_nz(rd, result) - } - /// `SUB` R-type instruction /// /// Perform val(rs1) - val(rs2) and store the result in `rd` @@ -397,6 +386,7 @@ where mod tests { use crate::{ backend_test, create_state, + interpreter::i::run_add, machine_state::{ csregisters::{ xstatus::{MPPValue, MStatus, SPPValue}, @@ -418,27 +408,6 @@ mod tests { prop_assert_eq, prop_assume, proptest, }; - backend_test!(test_add, F, { - let imm_rs1_res = [ - (0_i64, 0_u64, 0_u64), - (0, 0xFFF0_0420, 0xFFF0_0420), - (-1, 0, 0xFFFF_FFFF_FFFF_FFFF), - (1_000_000, -123_000_987_i64 as u64, -122_000_987_i64 as u64), - (1_000_000, 123_000_987, 124_000_987), - (-1, -321_000_000_000_i64 as u64, -321_000_000_001_i64 as u64), - ]; - - for (imm, rs1, res) in imm_rs1_res { - let mut state = create_state!(MachineCoreState, MachineCoreStateLayout, F, T1K); - - state.hart.xregisters.write(a0, rs1); - state.hart.xregisters.write(t0, imm as u64); - - state.hart.xregisters.run_add(a0, t0, nz::a0); - assert_eq!(state.hart.xregisters.read(a0), res); - } - }); - backend_test!(test_add_sub, F, { let imm_rs1_rd_res = [ (0_i64, 0_u64, t3, 0_u64), @@ -466,7 +435,7 @@ mod tests { state.hart.xregisters.write(t0, imm as u64); state.hart.xregisters.run_addi(imm, a0, rd); assert_eq!(state.hart.xregisters.read(rd), res); - state.hart.xregisters.run_add(a0, t0, nz::a0); + run_add(&mut state, nz::a0, nz::t0, nz::a0); assert_eq!(state.hart.xregisters.read(a0), res); // test sub with: res - imm = rs1 and res - rs1 = imm state.hart.xregisters.write(a0, res); diff --git a/src/riscv/lib/src/jit.rs b/src/riscv/lib/src/jit.rs index 9f900da6e14a..d1f5521f9d2e 100644 --- a/src/riscv/lib/src/jit.rs +++ b/src/riscv/lib/src/jit.rs @@ -478,4 +478,68 @@ mod tests { &jitted.struct_ref::(), ); }); + + backend_test!(test_add, F, { + use crate::machine_state::registers::NonZeroXRegister::*; + use Instruction as I; + + // Arrange + + // calculate fibonacci(4) == 5 + let scenario: &[I] = &[ + I::new_add(x2, x2, x1, Compressed), + I::new_add(x1, x1, x2, Uncompressed), + I::new_add(x2, x2, x1, Uncompressed), + I::new_add(x1, x1, x2, Compressed), + ]; + + let mut jit = JIT::::new().unwrap(); + + let mut interpreted = create_state!(MachineCoreState, MachineCoreStateLayout, F, T1K); + let mut jitted = create_state!(MachineCoreState, MachineCoreStateLayout, F, T1K); + let mut block = create_state!(BlockState, BlockLayout, F, T1K); + + block.construct(scenario); + + let mut interpreted_steps = 0; + let mut jitted_steps = 0; + + let initial_pc = 0; + interpreted.hart.pc.write(initial_pc); + jitted.hart.pc.write(initial_pc); + + interpreted.hart.xregisters.write_nz(x1, 1); + jitted.hart.xregisters.write_nz(x1, 1); + + // Act + let fun = jit + .compile(block.as_slice()) + .expect("Compilation of Mv should succeed"); + let mut block = block.interpreted_block(); + + let interpreted_res = block.run_block(&mut interpreted, initial_pc, &mut interpreted_steps); + let jitted_res = unsafe { + // # Safety - the jit is not dropped until after we + // exit the block. + fun.call(&mut jitted, initial_pc, &mut jitted_steps) + }; + + // Assert + assert_eq!(jitted_res, interpreted_res); + assert_eq!( + interpreted_steps, jitted_steps, + "Interpreted mode ran for {interpreted_steps}, compared to jit-mode of {jitted_steps}" + ); + + assert_eq!(interpreted_steps, scenario.len()); + + // have got to the fibonacci number 5 + assert_eq!(interpreted.hart.xregisters.read_nz(x1), 5); + assert_eq!(jitted.hart.xregisters.read_nz(x1), 5); + + assert_eq_struct( + &interpreted.struct_ref::(), + &jitted.struct_ref::(), + ); + }); } diff --git a/src/riscv/lib/src/machine_state.rs b/src/riscv/lib/src/machine_state.rs index 860c533d8f66..b981f5a9a6af 100644 --- a/src/riscv/lib/src/machine_state.rs +++ b/src/riscv/lib/src/machine_state.rs @@ -1253,8 +1253,8 @@ mod tests { opcode: OpCode::Add, args: TaggedArgs { rd: nz::a5.into(), - rs1: t1.into(), - rs2: t0.into(), + rs1: nz::t1.into(), + rs2: nz::t0.into(), ..TaggedArgs::DEFAULT }, }) diff --git a/src/riscv/lib/src/machine_state/block_cache.rs b/src/riscv/lib/src/machine_state/block_cache.rs index fb2022292609..9740c953607b 100644 --- a/src/riscv/lib/src/machine_state/block_cache.rs +++ b/src/riscv/lib/src/machine_state/block_cache.rs @@ -941,7 +941,7 @@ mod tests { }, main_memory::{self, tests::T1K}, mode::Mode, - registers::{a1, a2, nz, t0, t1}, + registers::{a1, nz, t0, t1}, MachineCoreState, MachineCoreStateLayout, MachineState, MachineStateLayout, TestCacheLayouts, }, @@ -1284,8 +1284,8 @@ mod tests { opcode: OpCode::Add, args: TaggedArgs { rd: nz::a1.into(), - rs1: a1.into(), - rs2: a2.into(), + rs1: nz::a1.into(), + rs2: nz::a2.into(), ..TaggedArgs::DEFAULT }, }) diff --git a/src/riscv/lib/src/machine_state/instruction.rs b/src/riscv/lib/src/machine_state/instruction.rs index 3c7d0e2928c3..0acfa7fcc38d 100644 --- a/src/riscv/lib/src/machine_state/instruction.rs +++ b/src/riscv/lib/src/machine_state/instruction.rs @@ -24,7 +24,7 @@ use super::{ use crate::{ default::ConstDefault, instruction_context::{IcbLoweringFn, ICB}, - interpreter::c, + interpreter::{c, i}, machine_state::ProgramCounterUpdate::{Next, Set}, parser::instruction::{ AmoArgs, CIBDTypeArgs, CIBNZTypeArgs, CIBTypeArgs, CJTypeArgs, CNZRTypeArgs, CRJTypeArgs, @@ -588,6 +588,7 @@ impl OpCode { Self::Mv => Some(Args::run_mv), Self::Nop => Some(Args::run_nop), Self::CAdd => Some(Args::run_cadd), + Self::Add => Some(Args::run_add), _ => None, } } @@ -698,6 +699,15 @@ macro_rules! impl_r_type { Ok(Next(self.width)) } }; + + ($impl: path, $fn: ident, non_zero) => { + // SAFETY: This function must only be called on an `Args` belonging + // to the same OpCode as the OpCode used to derive this function. + unsafe fn $fn(&self, icb: &mut I) -> ::IResult { + $impl(icb, self.rs1.nzx, self.rs2.nzx, self.rd.nzx); + icb.ok(Next(self.width)) + } + }; } macro_rules! impl_i_type { @@ -1063,7 +1073,7 @@ macro_rules! impl_f_r_type { impl Args { // RV64I R-type instructions - impl_r_type!(run_add, non_zero_rd); + impl_r_type!(i::run_add, run_add, non_zero); impl_r_type!(run_sub, non_zero_rd); impl_r_type!(run_xor, non_zero_rd); impl_r_type!(run_or, non_zero_rd); @@ -1357,10 +1367,7 @@ impl From<&InstrCacheable> for Instruction { fn from(value: &InstrCacheable) -> Self { match value { // RV64I R-type instructions - InstrCacheable::Add(args) => Instruction { - opcode: OpCode::Add, - args: args.into(), - }, + InstrCacheable::Add(args) => Instruction::from_ic_add(args), InstrCacheable::Sub(args) => Instruction { opcode: OpCode::Sub, args: args.into(), diff --git a/src/riscv/lib/src/machine_state/instruction/constructors.rs b/src/riscv/lib/src/machine_state/instruction/constructors.rs index 99040e267bc1..b94d38596157 100644 --- a/src/riscv/lib/src/machine_state/instruction/constructors.rs +++ b/src/riscv/lib/src/machine_state/instruction/constructors.rs @@ -4,11 +4,35 @@ use super::{Args, Instruction, OpCode}; use crate::{ - default::ConstDefault, machine_state::registers::NonZeroXRegister, - parser::instruction::InstrWidth, + default::ConstDefault, + machine_state::registers::NonZeroXRegister, + parser::{ + instruction::{InstrWidth, NonZeroRdRTypeArgs}, + split_x0, XRegisterParsed, + }, }; impl Instruction { + /// Create a new [`Instruction`] with the appropriate [`ArgsShape`] for the `Add` [`OpCode`]. + pub(crate) fn new_add( + rd: NonZeroXRegister, + rs1: NonZeroXRegister, + rs2: NonZeroXRegister, + width: InstrWidth, + ) -> Self { + Self { + opcode: OpCode::Add, + args: Args { + rd: rd.into(), + rs1: rs1.into(), + rs2: rs2.into(), + width, + ..Args::DEFAULT + }, + } + } + + /// Create a new [`Instruction`] with the appropriate [`ArgsShape`] for the `Mv` [`OpCode`]. pub(crate) fn new_mv(rd: NonZeroXRegister, rs2: NonZeroXRegister, width: InstrWidth) -> Self { Self { opcode: OpCode::Mv, @@ -43,6 +67,7 @@ impl Instruction { } } + /// Create a new [`Instruction`] with the appropriate [`ArgsShape`] for the `Li` [`OpCode`]. pub(crate) fn new_li(rd: NonZeroXRegister, imm: i64, width: InstrWidth) -> Self { Self { opcode: OpCode::Li, @@ -59,6 +84,7 @@ impl Instruction { } } + /// Create a new [`Instruction`] with the appropriate [`ArgsShape`] for the `Nop` [`OpCode`]. pub(crate) fn new_nop(width: InstrWidth) -> Self { Self { opcode: OpCode::Nop, @@ -74,3 +100,19 @@ impl Instruction { } } } + +impl Instruction { + /// Convert [`InstrCacheable::Add`] according to whether registers are non-zero. + pub(super) fn from_ic_add(args: &NonZeroRdRTypeArgs) -> Instruction { + use XRegisterParsed as X; + match (split_x0(args.rs1), split_x0(args.rs2)) { + (X::X0, X::X0) => Instruction::new_li(args.rd, 0, InstrWidth::Uncompressed), + (X::NonZero(rs1), X::X0) | (X::X0, X::NonZero(rs1)) => { + Instruction::new_mv(args.rd, rs1, InstrWidth::Uncompressed) + } + (X::NonZero(rs1), X::NonZero(rs2)) => { + Instruction::new_add(args.rd, rs1, rs2, InstrWidth::Uncompressed) + } + } + } +} diff --git a/src/riscv/lib/src/machine_state/instruction/tagged_instruction.rs b/src/riscv/lib/src/machine_state/instruction/tagged_instruction.rs index c77451c7ab9c..5b6bbebc1e0f 100644 --- a/src/riscv/lib/src/machine_state/instruction/tagged_instruction.rs +++ b/src/riscv/lib/src/machine_state/instruction/tagged_instruction.rs @@ -351,12 +351,12 @@ pub fn opcode_to_argsshape(opcode: &OpCode) -> ArgsShape { Fsw | Fsd | CFsd | CFsdsp => ArgsShape::XSrcFSrc, - Mv | CAdd | CJr | CJalr | CAddi | CAddiw | Li | CLui | CSlli | CLdsp | CLwsp | Nop => { - ArgsShape::NZXSrcNZXDest - } - Andi | Ori | Xori | Addiw | Add | Sub | And | Or | Xor | Sll | Srl | Sra | Addw | Subw - | Sllw | Srlw | Sraw | Slti | Sltiu | Slli | Srli | Srai | Slliw | Srliw | Sraiw | Slt - | Sltu | Lui | Auipc => ArgsShape::XSrcNZXDest, + Add | Mv | CAdd | CJr | CJalr | CAddi | CAddiw | Li | CLui | CSlli | CLdsp | CLwsp + | Nop => ArgsShape::NZXSrcNZXDest, + + Andi | Ori | Xori | Addiw | Sub | And | Or | Xor | Sll | Srl | Sra | Addw | Subw | Sllw + | Srlw | Sraw | Slti | Sltiu | Slli | Srli | Srai | Slliw | Srliw | Sraiw | Slt | Sltu + | Lui | Auipc => ArgsShape::XSrcNZXDest, } } @@ -377,8 +377,8 @@ mod tests { opcode: OpCode::Add, args: Args { rd: NonZeroXRegister::x1.into(), - rs1: XRegister::x0.into(), - rs2: XRegister::x0.into(), + rs1: NonZeroXRegister::x2.into(), + rs2: NonZeroXRegister::x2.into(), ..Args::DEFAULT }, }; diff --git a/src/riscv/lib/src/parser.rs b/src/riscv/lib/src/parser.rs index d200b0431001..a32eaafbc827 100644 --- a/src/riscv/lib/src/parser.rs +++ b/src/riscv/lib/src/parser.rs @@ -16,6 +16,7 @@ use crate::machine_state::{ use arbitrary_int::{u3, u5}; use core::ops::Range; use instruction::*; +use std::fmt::{self, Display, Formatter}; /// Given an instruction encoded as a little-endian `u32`, extract `n` bits /// starting at `pos`. @@ -1164,19 +1165,28 @@ const C_Q1_3: u16 = 0b11; /// Wrapper for splitting x0 from other XRegisters that can /// be represented by [`NonZeroXRegister`]. #[derive(Debug, PartialEq, Eq, Clone, Copy, Hash, serde::Serialize, serde::Deserialize)] -enum XRegisterParsed { +pub(crate) enum XRegisterParsed { X0, NonZero(NonZeroXRegister), } /// Convert [`XRegister`] to [`NonZeroXRegister`] when `r != x0`. -const fn split_x0(r: XRegister) -> XRegisterParsed { +pub(crate) const fn split_x0(r: XRegister) -> XRegisterParsed { match r { x0 => XRegisterParsed::X0, r => XRegisterParsed::NonZero(NonZeroXRegister::assert_from(r)), } } +impl Display for XRegisterParsed { + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { + match self { + XRegisterParsed::X0 => write!(f, "zero"), + XRegisterParsed::NonZero(r) => write!(f, "{}", r), + } + } +} + #[inline] const fn parse_compressed_instruction_inner(instr: u16) -> Instr { use InstrCacheable::*; diff --git a/src/riscv/lib/src/parser/instruction.rs b/src/riscv/lib/src/parser/instruction.rs index d04610c1655f..648c17b6d6af 100644 --- a/src/riscv/lib/src/parser/instruction.rs +++ b/src/riscv/lib/src/parser/instruction.rs @@ -22,6 +22,7 @@ pub struct RTypeArgs { pub rs2: XRegister, } +/// Intermediate representation of Args for R-type instructions with guaranteed `rd` != `x0`. #[derive(Debug, PartialEq, Eq, Clone, Copy, Hash, serde::Serialize, serde::Deserialize)] pub struct NonZeroRdRTypeArgs { pub rd: NonZeroXRegister, @@ -36,6 +37,7 @@ pub struct ITypeArgs { pub imm: i64, } +/// Intermediate representation of Args for I-type instructions with guaranteed `rd` != `x0`. #[derive(Debug, PartialEq, Eq, Clone, Copy, Hash, serde::Serialize, serde::Deserialize)] pub struct NonZeroRdITypeArgs { pub rd: NonZeroXRegister, @@ -268,6 +270,7 @@ pub struct CSSDTypeArgs { )] pub enum InstrCacheable { // RV64I R-type instructions + /// `ADD` - Perform val(rs1) + val(rs2) and store the result in `rd` Add(NonZeroRdRTypeArgs), Sub(NonZeroRdRTypeArgs), Xor(NonZeroRdRTypeArgs), diff --git a/src/riscv/lib/tests/expected/jstz/state_hash_final b/src/riscv/lib/tests/expected/jstz/state_hash_final index 5ccdb4ada01c..50e760c86cdd 100644 --- a/src/riscv/lib/tests/expected/jstz/state_hash_final +++ b/src/riscv/lib/tests/expected/jstz/state_hash_final @@ -1 +1 @@ -Hash { digest: [70, 226, 188, 11, 81, 189, 174, 50, 250, 34, 176, 31, 253, 107, 70, 12, 97, 186, 30, 218, 111, 142, 187, 141, 5, 57, 104, 48, 127, 34, 206, 169] } +Hash { digest: [118, 68, 133, 219, 100, 205, 79, 248, 22, 113, 153, 179, 169, 230, 127, 26, 116, 70, 142, 12, 98, 208, 13, 252, 181, 169, 219, 92, 148, 202, 3, 172] } -- GitLab From 588ce09d9138e24a012de0a196393a8c190dd5a1 Mon Sep 17 00:00:00 2001 From: Neelay Sant Date: Tue, 4 Feb 2025 12:26:26 +0000 Subject: [PATCH 2/2] RISC-V: Deduplicate CAdd OpCode into Add --- src/riscv/lib/src/interpreter/c.rs | 14 +--- src/riscv/lib/src/jit.rs | 64 ------------------- .../lib/src/machine_state/instruction.rs | 6 +- .../machine_state/instruction/constructors.rs | 19 ------ .../instruction/tagged_instruction.rs | 5 +- src/riscv/lib/src/parser/instruction.rs | 2 + .../lib/tests/expected/jstz/state_hash_final | 2 +- 7 files changed, 9 insertions(+), 103 deletions(-) diff --git a/src/riscv/lib/src/interpreter/c.rs b/src/riscv/lib/src/interpreter/c.rs index d079508db5dc..4b030ba3a912 100644 --- a/src/riscv/lib/src/interpreter/c.rs +++ b/src/riscv/lib/src/interpreter/c.rs @@ -8,17 +8,6 @@ use crate::{instruction_context::ICB, machine_state::registers::NonZeroXRegister}; -/// `C.ADD` CR-type compressed instruction -/// -/// Adds the values in registers `rd_rs1` and `rs2` and writes the result -/// back to register `rd_rs1`. -pub fn run_cadd(icb: &mut impl ICB, rd_rs1: NonZeroXRegister, rs2: NonZeroXRegister) { - let lhs = icb.xregister_read(rd_rs1); - let rhs = icb.xregister_read(rs2); - let result = icb.xvalue_wrapping_add(lhs, rhs); - icb.xregister_write(rd_rs1, result) -} - /// Copies the value in register `rs2` into register `rd_rs1`. /// /// Relevant RISC-V opcodes: @@ -40,6 +29,7 @@ mod tests { use crate::machine_state::MachineCoreState; use crate::{ backend_test, create_state, + interpreter::i::run_add, machine_state::{main_memory::tests::T1K, registers::nz, MachineCoreStateLayout}, }; @@ -59,7 +49,7 @@ mod tests { state.hart.xregisters.write_nz(nz::a3, rs1); state.hart.xregisters.write_nz(nz::a4, imm as u64); - run_cadd(&mut state, nz::a3, nz::a4); + run_add(&mut state, nz::a3, nz::a4, nz::a3); assert_eq!(state.hart.xregisters.read_nz(nz::a3), res); run_mv(&mut state, nz::a4, nz::a3); assert_eq!(state.hart.xregisters.read_nz(nz::a4), res); diff --git a/src/riscv/lib/src/jit.rs b/src/riscv/lib/src/jit.rs index d1f5521f9d2e..1997ac250e92 100644 --- a/src/riscv/lib/src/jit.rs +++ b/src/riscv/lib/src/jit.rs @@ -415,70 +415,6 @@ mod tests { } }); - backend_test!(test_cadd, F, { - use crate::machine_state::registers::NonZeroXRegister::*; - use Instruction as I; - - // Arrange - - // calculate fibonacci(4) == 5 - let scenario: &[I] = &[ - I::new_cadd(x2, x1, Compressed), - I::new_cadd(x1, x2, Uncompressed), - I::new_cadd(x2, x1, Uncompressed), - I::new_cadd(x1, x2, Compressed), - ]; - - let mut jit = JIT::::new().unwrap(); - - let mut interpreted = create_state!(MachineCoreState, MachineCoreStateLayout, F, T1K); - let mut jitted = create_state!(MachineCoreState, MachineCoreStateLayout, F, T1K); - let mut block = create_state!(BlockState, BlockLayout, F, T1K); - - block.construct(scenario); - - let mut interpreted_steps = 0; - let mut jitted_steps = 0; - - let initial_pc = 0; - interpreted.hart.pc.write(initial_pc); - jitted.hart.pc.write(initial_pc); - - interpreted.hart.xregisters.write_nz(x1, 1); - jitted.hart.xregisters.write_nz(x1, 1); - - // Act - let fun = jit - .compile(block.as_slice()) - .expect("Compilation of Mv should succeed"); - let mut block = block.interpreted_block(); - - let interpreted_res = block.run_block(&mut interpreted, initial_pc, &mut interpreted_steps); - let jitted_res = unsafe { - // # Safety - the jit is not dropped until after we - // exit the for loop - fun.call(&mut jitted, initial_pc, &mut jitted_steps) - }; - - // Assert - assert_eq!(jitted_res, interpreted_res); - assert_eq!( - interpreted_steps, jitted_steps, - "Interpreted mode ran for {interpreted_steps}, compared to jit-mode of {jitted_steps}" - ); - - assert_eq!(interpreted_steps, scenario.len()); - - // have got to the fibonacci number 5 - assert_eq!(interpreted.hart.xregisters.read_nz(x1), 5); - assert_eq!(jitted.hart.xregisters.read_nz(x1), 5); - - assert_eq_struct( - &interpreted.struct_ref::(), - &jitted.struct_ref::(), - ); - }); - backend_test!(test_add, F, { use crate::machine_state::registers::NonZeroXRegister::*; use Instruction as I; diff --git a/src/riscv/lib/src/machine_state/instruction.rs b/src/riscv/lib/src/machine_state/instruction.rs index 0acfa7fcc38d..bf1d84b1a03d 100644 --- a/src/riscv/lib/src/machine_state/instruction.rs +++ b/src/riscv/lib/src/machine_state/instruction.rs @@ -339,7 +339,6 @@ pub enum OpCode { CAddi16sp, CAddi4spn, CSlli, - CAdd, CAnd, COr, CXor, @@ -549,7 +548,6 @@ impl OpCode { Self::CAddi4spn => Args::run_caddi4spn, Self::CSlli => Args::run_cslli, Self::Mv => Args::run_mv, - Self::CAdd => Args::run_cadd, Self::CAnd => Args::run_cand, Self::COr => Args::run_cor, Self::CXor => Args::run_cxor, @@ -587,7 +585,6 @@ impl OpCode { match self { Self::Mv => Some(Args::run_mv), Self::Nop => Some(Args::run_nop), - Self::CAdd => Some(Args::run_cadd), Self::Add => Some(Args::run_add), _ => None, } @@ -1281,7 +1278,6 @@ impl Args { impl_csr_imm_type!(run_csrrci); // RV32C compressed instructions - impl_cr_nz_type!(c::run_cadd, run_cadd); impl_cr_nz_type!(c::run_mv, run_mv); impl_load_type!(run_clw); impl_cload_sp_type!(run_clwsp); @@ -2068,7 +2064,7 @@ impl From<&InstrCacheable> for Instruction { Instruction::new_mv(args.rd_rs1, args.rs2, InstrWidth::Compressed) } InstrCacheable::CAdd(args) => { - Instruction::new_cadd(args.rd_rs1, args.rs2, InstrWidth::Compressed) + Instruction::new_add(args.rd_rs1, args.rd_rs1, args.rs2, InstrWidth::Compressed) } InstrCacheable::CAnd(args) => Instruction { opcode: OpCode::CAnd, diff --git a/src/riscv/lib/src/machine_state/instruction/constructors.rs b/src/riscv/lib/src/machine_state/instruction/constructors.rs index b94d38596157..c5d6b8249b7a 100644 --- a/src/riscv/lib/src/machine_state/instruction/constructors.rs +++ b/src/riscv/lib/src/machine_state/instruction/constructors.rs @@ -48,25 +48,6 @@ impl Instruction { } } - pub(crate) fn new_cadd( - rd_rs1: NonZeroXRegister, - rs2: NonZeroXRegister, - width: InstrWidth, - ) -> Self { - Self { - opcode: OpCode::CAdd, - args: Args { - rd: rd_rs1.into(), - // We are adding a default value for rs1 as NonZeroXRegister::x1 - // to be explicit that it is of NonZeroXRegister type. - rs1: NonZeroXRegister::x1.into(), - rs2: rs2.into(), - width, - ..Args::DEFAULT - }, - } - } - /// Create a new [`Instruction`] with the appropriate [`ArgsShape`] for the `Li` [`OpCode`]. pub(crate) fn new_li(rd: NonZeroXRegister, imm: i64, width: InstrWidth) -> Self { Self { diff --git a/src/riscv/lib/src/machine_state/instruction/tagged_instruction.rs b/src/riscv/lib/src/machine_state/instruction/tagged_instruction.rs index 5b6bbebc1e0f..eeb77fa39ff0 100644 --- a/src/riscv/lib/src/machine_state/instruction/tagged_instruction.rs +++ b/src/riscv/lib/src/machine_state/instruction/tagged_instruction.rs @@ -351,8 +351,9 @@ pub fn opcode_to_argsshape(opcode: &OpCode) -> ArgsShape { Fsw | Fsd | CFsd | CFsdsp => ArgsShape::XSrcFSrc, - Add | Mv | CAdd | CJr | CJalr | CAddi | CAddiw | Li | CLui | CSlli | CLdsp | CLwsp - | Nop => ArgsShape::NZXSrcNZXDest, + Add | Mv | CJr | CJalr | CAddi | CAddiw | Li | CLui | CSlli | CLdsp | CLwsp | Nop => { + ArgsShape::NZXSrcNZXDest + } Andi | Ori | Xori | Addiw | Sub | And | Or | Xor | Sll | Srl | Sra | Addw | Subw | Sllw | Srlw | Sraw | Slti | Sltiu | Slli | Srli | Srai | Slliw | Srliw | Sraiw | Slt | Sltu diff --git a/src/riscv/lib/src/parser/instruction.rs b/src/riscv/lib/src/parser/instruction.rs index 648c17b6d6af..67a9c35933e2 100644 --- a/src/riscv/lib/src/parser/instruction.rs +++ b/src/riscv/lib/src/parser/instruction.rs @@ -466,6 +466,8 @@ pub enum InstrCacheable { CAndi(CIBTypeArgs), /// `C.MV` - Copies the value in register `rs2` into register `rd_rs1`. CMv(CNZRTypeArgs), + /// `C.ADD` - Adds the values in registers `rd_rs1` and `rs2` and writes the result + /// back to register `rd_rs1`. CAdd(CNZRTypeArgs), CAnd(CRTypeArgs), COr(CRTypeArgs), diff --git a/src/riscv/lib/tests/expected/jstz/state_hash_final b/src/riscv/lib/tests/expected/jstz/state_hash_final index 50e760c86cdd..300e3c9e7524 100644 --- a/src/riscv/lib/tests/expected/jstz/state_hash_final +++ b/src/riscv/lib/tests/expected/jstz/state_hash_final @@ -1 +1 @@ -Hash { digest: [118, 68, 133, 219, 100, 205, 79, 248, 22, 113, 153, 179, 169, 230, 127, 26, 116, 70, 142, 12, 98, 208, 13, 252, 181, 169, 219, 92, 148, 202, 3, 172] } +Hash { digest: [134, 251, 171, 73, 20, 75, 244, 189, 12, 157, 121, 210, 196, 228, 1, 77, 175, 210, 206, 24, 56, 72, 50, 136, 90, 128, 142, 191, 126, 255, 140, 95] } -- GitLab