From 801b165e703b9113f5453db7c48a690621d7e635 Mon Sep 17 00:00:00 2001 From: Alban Dutilleul Date: Tue, 4 Jul 2023 09:56:26 +0100 Subject: [PATCH] fix various semantic mismatchs in RV32F (#27) --- examples/mul-float.asm | 11 +++++++++++ riscemu/instructions/RV32F.py | 30 +++++++++++++++--------------- riscemu/instructions/RV_Debug.py | 8 +++++++- riscemu/types/float32.py | 7 +------ test/test_float32.py | 4 ++++ 5 files changed, 38 insertions(+), 22 deletions(-) create mode 100644 examples/mul-float.asm diff --git a/examples/mul-float.asm b/examples/mul-float.asm new file mode 100644 index 0000000..f7f4198 --- /dev/null +++ b/examples/mul-float.asm @@ -0,0 +1,11 @@ +main: + li a1, 1084227584 + li a2, 1082130432 + fcvt.s.wu ft0, a1 + fcvt.s.wu ft1, a2 + fmul.s ft6, ft0, ft1 + print.float ft6 + // exit gracefully + addi a0, zero, 0 + addi a7, zero, 93 + scall // exit with code 0 diff --git a/riscemu/instructions/RV32F.py b/riscemu/instructions/RV32F.py index 9eff582..7dda548 100644 --- a/riscemu/instructions/RV32F.py +++ b/riscemu/instructions/RV32F.py @@ -121,7 +121,7 @@ class RV32F(InstructionSet): rd, rs1, rs2 = self.parse_rd_rs_rs(ins) self.regs.set_f( rd, - self.regs.get_f(rs1) + self.regs.get_f(rs2), + rs1 + rs2, ) def instruction_fsub_s(self, ins: Instruction): @@ -145,7 +145,7 @@ class RV32F(InstructionSet): rd, rs1, rs2 = self.parse_rd_rs_rs(ins) self.regs.set_f( rd, - self.regs.get_f(rs1) - self.regs.get_f(rs2), + rs1 - rs2, ) def instruction_fmul_s(self, ins: Instruction): @@ -169,7 +169,7 @@ class RV32F(InstructionSet): rd, rs1, rs2 = self.parse_rd_rs_rs(ins) self.regs.set_f( rd, - self.regs.get_f(rs1) * self.regs.get_f(rs2), + rs1 * rs2, ) def instruction_fdiv_s(self, ins: Instruction): @@ -193,7 +193,7 @@ class RV32F(InstructionSet): rd, rs1, rs2 = self.parse_rd_rs_rs(ins) self.regs.set_f( rd, - self.regs.get_f(rs1) / self.regs.get_f(rs2), + rs1 / rs2, ) def instruction_fsqrt_s(self, ins: Instruction): @@ -215,7 +215,7 @@ class RV32F(InstructionSet): | f[rd] = sqrt(f[rs1]) """ rd, rs = self.parse_rd_rs(ins) - self.regs.set_f(self.regs.get_f(rs) ** 0.5) + self.regs.set_f(rd, self.regs.get_f(rs) ** 0.5) def instruction_fsgnj_s(self, ins: Instruction): """ @@ -300,8 +300,8 @@ class RV32F(InstructionSet): rd, Float32( min( - self.regs.get_f(rs1).value, - self.regs.get_f(rs2).value, + rs1.value, + rs2.value, ) ), ) @@ -328,8 +328,8 @@ class RV32F(InstructionSet): rd, Float32( max( - self.regs.get_f(rs1).value, - self.regs.get_f(rs2).value, + rs1.value, + rs2.value, ) ), ) @@ -352,7 +352,7 @@ class RV32F(InstructionSet): | x[rd] = sext(s32_{f32}(f[rs1])) """ rd, rs = self.parse_rd_rs(ins) - self.regs.set(rd, Int32(self.regs.get_f(rs).value)) + self.regs.set(rd, Int32(self.regs.get_f(rs).bytes)) def instruction_fcvt_wu_s(self, ins: Instruction): """ @@ -372,7 +372,7 @@ class RV32F(InstructionSet): | x[rd] = sext(u32_{f32}(f[rs1])) """ rd, rs = self.parse_rd_rs(ins) - self.regs.set(rd, UInt32(self.regs.get_f(rs).value)) + self.regs.set(rd, UInt32(self.regs.get_f(rs).bytes)) def instruction_fmv_x_w(self, ins: Instruction): """ @@ -500,7 +500,7 @@ class RV32F(InstructionSet): | f[rd] = f32_{s32}(x[rs1]) """ rd, rs = self.parse_rd_rs(ins) - self.regs.set_f(rd, Float32(self.regs.get(rs).signed().value)) + self.regs.set_f(rd, Float32.from_bytes(self.regs.get(rs).signed().value)) def instruction_fcvt_s_wu(self, ins: Instruction): """ @@ -520,7 +520,7 @@ class RV32F(InstructionSet): | f[rd] = f32_{u32}(x[rs1]) """ rd, rs = self.parse_rd_rs(ins) - self.regs.set_f(rd, Float32(self.regs.get(rs).unsigned_value)) + self.regs.set_f(rd, Float32.from_bytes(self.regs.get(rs).unsigned_value)) def instruction_fmv_w_x(self, ins: Instruction): """ @@ -562,7 +562,7 @@ class RV32F(InstructionSet): | f[rd] = M[x[rs1] + sext(offset)][31:0] """ rd, addr = self.parse_mem_ins(ins) - self.regs.set_f(rd, self.mmu.read_float(addr)) + self.regs.set_f(rd, self.mmu.read_float(addr.value)) def instruction_fsw(self, ins: Instruction): """ @@ -583,7 +583,7 @@ class RV32F(InstructionSet): """ rs, addr = self.parse_mem_ins(ins) val = self.regs.get_f(rs) - self.mmu.write(addr, 4, bytearray(val.bytes)) + self.mmu.write(addr.value, 4, bytearray(val.bytes)) def parse_rd_rs(self, ins: Instruction) -> Tuple[str, str]: assert len(ins.args) == 2 diff --git a/riscemu/instructions/RV_Debug.py b/riscemu/instructions/RV_Debug.py index ad31181..efb143d 100644 --- a/riscemu/instructions/RV_Debug.py +++ b/riscemu/instructions/RV_Debug.py @@ -6,6 +6,10 @@ class RV_Debug(InstructionSet): reg = ins.get_reg(0) print("register {} contains value {}".format(reg, self.regs.get(reg))) + def instruction_print_float(self, ins: Instruction): + reg = ins.get_reg(0) + print("register {} contains value {}".format(reg, self.regs.get_f(reg).value)) + def instruction_print_uint(self, ins: Instruction): reg = ins.get_reg(0) print( @@ -16,7 +20,9 @@ class RV_Debug(InstructionSet): def instruction_print_hex(self, ins: Instruction): reg = ins.get_reg(0) - print("register {} contains value {}".format(reg, hex(self.regs.get(reg)))) + print( + "register {} contains value {}".format(reg, hex(self.regs.get(reg).value)) + ) def instruction_print_uhex(self, ins: Instruction): reg = ins.get_reg(0) diff --git a/riscemu/types/float32.py b/riscemu/types/float32.py index 5ae2a77..adf50c0 100644 --- a/riscemu/types/float32.py +++ b/riscemu/types/float32.py @@ -34,7 +34,7 @@ class Float32: @classmethod def from_bytes(cls, val: Union[int, bytes_t, bytearray]): if isinstance(val, int): - val = int.to_bytes(byteorder="little") + val = struct.unpack("!f", struct.pack("!I", val))[0] return Float32(val) def __init__( @@ -134,11 +134,6 @@ class Float32: def __bool__(self): return bool(self.value) - def __cmp__(self, other: Any): - if isinstance(other, Float32): - other = other.value - return self.value.__cmp__(other) - def __pow__(self, power, modulo=None): if modulo is not None: raise ValueError("Float32 pow with modulo unsupported") diff --git a/test/test_float32.py b/test/test_float32.py index 7c29c5a..a045302 100644 --- a/test/test_float32.py +++ b/test/test_float32.py @@ -19,3 +19,7 @@ def test_random_float_ops(): assert val - 2 == 3 assert val * val == 25 assert Float32(9) ** 0.5 == 3 + + +def test_float_from_raw_int_conversion(): + assert Float32.from_bytes(1084227584) == Float32(5.0)