From 1fcf4146868305360cda778cb726cdc4108348e0 Mon Sep 17 00:00:00 2001 From: root Date: Thu, 8 May 2025 17:20:33 +0000 Subject: [PATCH 01/11] Add function to convert a Floating point number to 32-bit integer --- arch/isa/fp.idl | 41 +++++++++++++++++++++++++++++++++++++++-- 1 file changed, 39 insertions(+), 2 deletions(-) diff --git a/arch/isa/fp.idl b/arch/isa/fp.idl index 335c73ef2..26a58c152 100644 --- a/arch/isa/fp.idl +++ b/arch/isa/fp.idl @@ -875,7 +875,7 @@ function i32_to_f32 { U32 a, RoundingMode mode description { - Converts 32-bit signed integer to 32-bit floating point + Converts 32-bit signed integer to 32-bit floating point number } body { # sign of integer, it is 1 when negative @@ -894,7 +894,7 @@ function ui32_to_f32 { U32 a, RoundingMode mode description { - Converts 32-bit unsigned integer to 32-bit floating point + Converts 32-bit unsigned integer to 32-bit floating point number } body { # sign of integer, it is 1 when negative @@ -908,3 +908,40 @@ function ui32_to_f32 { } } } + +function f32_to_i32 { + returns U32 + arguments + U32 a, + RoundingMode mode + description { + Converts 32-bit floating point number to a signed 32-bit integer + } + body { + Bits<1> sign = signF32UI(a); + Bits<8> exp = expF32UI(a); + Bits<23> sig = fracF32UI(a); + Bits<8> shiftDist; + U64 sig64; + # for NaN return the highest positive value and set floating-point flag to invalid. + if ((exp == 8'hFF) && (sig != 0)) { + sign = 0; + set_fp_flag(FpFlag::NV); + return 32'h7FFFFFFF; + } + + # MSB of significand is set to 1 because minimum 32-bit integer in IEEE 754 is 32'h80000000 + if (exp != 0) { + sig = sig | 32'h00800000; + } + + sig64 = sig << 32; + shiftDist = 8'hAA - exp; + + if (shiftDist > 0) { + sig64 = softfloat_shiftRightJam64( sig64, shiftDist); + } + + return softfloat_roundToI32(sign, sig64, mode); + } +} From 461a007ad4e9b25e5201509047ebed777a70a89d Mon Sep 17 00:00:00 2001 From: Shashank V M Date: Fri, 9 May 2025 16:30:08 +0000 Subject: [PATCH 02/11] Add IDL for converting 32-bit Floating point number to 32-bit signed and unsigned integer --- arch/inst/F/fcvt.w.s.yaml | 26 +--------- arch/inst/F/fcvt.wu.s.yaml | 35 +++++++++++-- arch/isa/fp.idl | 104 +++++++++++++++++++++++++++++++++++-- 3 files changed, 134 insertions(+), 31 deletions(-) diff --git a/arch/inst/F/fcvt.w.s.yaml b/arch/inst/F/fcvt.w.s.yaml index b2eb01c09..3f45df278 100644 --- a/arch/inst/F/fcvt.w.s.yaml +++ b/arch/inst/F/fcvt.w.s.yaml @@ -5,7 +5,7 @@ kind: instruction name: fcvt.w.s long_name: Convert single-precision float to integer word to signed 32-bit integer description: | - Converts a floating-point number in floating-point register _fs1_ to a signed 32-bit integer indicates + Converts a floating-point number in floating-point register _fs1_ to a signed 32-bit integer in integer register _rd_. For XLEN >32, `fcvt.w.s` sign-extends the 32-bit result to the destination register width. @@ -54,30 +54,8 @@ access: data_independent_timing: true operation(): | check_f_ok($encoding); - - Bits<32> sp_value = f[fs1][31:0]; - - Bits<1> sign = sp_value[31]; - Bits<8> exp = sp_value[30:23]; - Bits<23> sig = sp_value[22:0]; - RoundingMode rounding_mode = rm_to_mode(rm, $encoding); - - if ( (exp == 0xff) && (sig != 0)) { - sign = 0; - set_fp_flag(FpFlag::NV); - X[rd] = SP_CANONICAL_NAN; - } else { - if (exp != 0) { - sig = sig | 0x00800000; - } - Bits<64> sig64 = sig << 32; - Bits<16> shift_dist = 0xAA - exp; - if (0 < shift_dist) { - sig64 = softfloat_shiftRightJam64(sig64, shift_dist ); - } - X[rd] = softfloat_roundToI32( sign, sig64, rounding_mode ); - } + X[rd] = f32_to_i32(X[fs1], mode); # SPDX-SnippetBegin # SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model diff --git a/arch/inst/F/fcvt.wu.s.yaml b/arch/inst/F/fcvt.wu.s.yaml index deb8b64ef..481f54e7a 100644 --- a/arch/inst/F/fcvt.wu.s.yaml +++ b/arch/inst/F/fcvt.wu.s.yaml @@ -3,9 +3,36 @@ $schema: "inst_schema.json#" kind: instruction name: fcvt.wu.s -long_name: No synopsis available +long_name: Convert single-precision float to integer word to unsigned 32-bit integer description: | - No description available. + Converts a floating-point number in floating-point register _fs1_ to an unsigned 32-bit integer in integer register _rd_. + + For XLEN >32, `fcvt.wu.s` sign-extends the 32-bit result to the destination register width. + + If the rounded result is not representable as a 32-bit unsigned integer, it is clipped to the + nearest value and the invalid flag is set. + + The range of valid inputs and behavior for invalid inputs are: + + [separator="!"] + !=== + ! ! Value + + h! Minimum valid input (after rounding) ! `0` + h! Maximum valid input (after rounding) ! `2^32 - 1` + h! Output for out-of-range negative input ! `0` + h! Output for `-∞` ! `0` + h! Output for out-of-range positive input ! `2^32 - 1` + h! Output for `+∞` for `NaN` ! `2^32 - 1` + !=== + + All floating-point to integer and integer to floating-point conversion instructions round + according to the _rm_ field. + A floating-point register can be initialized to floating-point positive zero using + `fcvt.s.w rd, x0`, which will never set any exception flags. + + All floating-point conversion instructions set the Inexact exception flag if the rounded + result differs from the operand value and the Invalid exception flag is not set. definedBy: F assembly: xd, fs1, rm encoding: @@ -24,7 +51,9 @@ access: vu: always data_independent_timing: true operation(): | - + check_f_ok($encoding); + RoundingMode rounding_mode = rm_to_mode(rm, $encoding); + X[rd] = f32_to_ui32(X[fs1], mode); # SPDX-SnippetBegin # SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model # SPDX-License-Identifier: BSD-2-Clause diff --git a/arch/isa/fp.idl b/arch/isa/fp.idl index 26a58c152..3fa07432b 100644 --- a/arch/isa/fp.idl +++ b/arch/isa/fp.idl @@ -20,8 +20,15 @@ Bits<32> SP_NEG_ZERO = 32'b1_00000000_00000000000000000000000; Bits<32> SP_CANONICAL_NAN = 32'b0_11111111_10000000000000000000000; Bits<16> HP_CANONICAL_NAN = 16'b0_11111_1000000000; -Bits<32> WORD_NEG_OVERFLOW = 32'h8000_0000; # minimum 32-bit integer -Bits<32> WORD_POS_OVERFLOW = 32'h7FFF_FFFF; # maximum 32-bit integer +Bits<32> WORD_NEG_OVERFLOW = 32'h8000_0000; # minimum signed 32-bit integer +Bits<32> WORD_POS_OVERFLOW = 32'h7FFF_FFFF; # maximum signed 32-bit integer + +Bits<32> UI32_NEG_OVERFLOW = 32'h0000_0000; # minimum unsigned 32-bit integer +Bits<32> UI32_POS_OVERFLOW = 32'hFFFF_FFFF; # maximum unsigned 32-bit integer + +Bits<32> UI32_NAN = 32'hFFFF_FFFF; # NaN to unsigned 32-bit integer +Bits<32> I32_NAN = 32'h7FFF_FFFF; # NaN to signed 32-bit integer + enum RoundingMode { RNE 0b000 # Round to Nearest, ties to Even @@ -331,7 +338,7 @@ function softfloat_roundToI32 { Bits<64> sig, RoundingMode roundingMode description { - Round to unsigned 32-bit integer, using +rounding_mode+ + Round to signed 32-bit integer, using +rounding_mode+ } body { Bits<16> roundIncrement = 0x800; @@ -375,6 +382,58 @@ function softfloat_roundToI32 { } } +function softfloat_roundToUI32 { + returns Bits<32> + arguments + Bits<1> sign, + Bits<64> sig, + RoundingMode roundingMode + description { + Round to unsigned 32-bit integer, using +rounding_mode+ + } + body { + Bits<16> roundIncrement = 0x800; + if ( + (roundingMode != RoundingMode::RMM) + && (roundingMode != RoundingMode::RNE) + ) { + roundIncrement = 0; + if ( sign == 1) { + if (sig == 0) return 0; + if (roundingMode == RoundingMode::RDN) set_fp_flag(FpFlag::NV); + } else { + if (roundingMode == RoundingMode::RUP) roundIncrement = 0xFFF; + } + } + + Bits<16> roundBits = sig & 0xFFF; + sig = sig + roundIncrement; + if ((sig & 0xFFFFF00000000000) != 0) { + set_fp_flag(FpFlag::NV); + return sign == 1 ? UI32_NEG_OVERFLOW : UI32_POS_OVERFLOW; + } + + Bits<32> z = sig >> 12; + if ( + (roundBits == 0x800 && (roundingMode == RoundingMode::RNE)) + ) { + z = z & ~32'b1; + } + + + + if ((z != 0) && (sign == 1)) { + set_fp_flag(FpFlag::NV); + return sign == 1 ? UI32_NEG_OVERFLOW : UI32_POS_OVERFLOW; + } + + if (roundBits != 0) { + set_fp_flag(FpFlag::NX); + } + return z; + } +} + function packToF32UI { returns Bits<32> arguments @@ -927,7 +986,7 @@ function f32_to_i32 { if ((exp == 8'hFF) && (sig != 0)) { sign = 0; set_fp_flag(FpFlag::NV); - return 32'h7FFFFFFF; + return I32_NAN; } # MSB of significand is set to 1 because minimum 32-bit integer in IEEE 754 is 32'h80000000 @@ -945,3 +1004,40 @@ function f32_to_i32 { return softfloat_roundToI32(sign, sig64, mode); } } + +function f32_to_ui32 { + returns U32 + arguments + U32 a, + RoundingMode mode + description { + Converts 32-bit floating point number to an unsigned 32-bit integer + } + body { + Bits<1> sign = signF32UI(a); + Bits<8> exp = expF32UI(a); + Bits<23> sig = fracF32UI(a); + Bits<8> shiftDist; + U64 sig64; + # for NaN return the highest positive value and set floating-point flag to invalid. + if ((exp == 8'hFF) && (sig != 0)) { + sign = 0; + set_fp_flag(FpFlag::NV); + return UI32_NAN; + } + + # MSB of significand is set to 1 because minimum 32-bit integer in IEEE 754 is 32'h80000000 + if (exp != 0) { + sig = sig | 32'h00800000; + } + + sig64 = sig << 32; + shiftDist = 8'hAA - exp; + + if (shiftDist > 0) { + sig64 = softfloat_shiftRightJam64( sig64, shiftDist); + } + + return softfloat_roundToUI32(sign, sig64, mode); + } +} From 2dd062f614643a1430536f7ae5ed85c9722ff755 Mon Sep 17 00:00:00 2001 From: Shashank V M Date: Sun, 13 Jul 2025 13:24:35 +0000 Subject: [PATCH 03/11] fix: move files to Zfa folder --- spec/std/isa/inst/{F => Zfa}/fli.s.yaml | 0 spec/std/isa/inst/{F => Zfa}/fmaxm.s.yaml | 0 spec/std/isa/inst/{F => Zfa}/fminm.s.yaml | 0 spec/std/isa/inst/{F => Zfa}/fround.s.yaml | 19 +++++++++++++++++-- spec/std/isa/inst/{F => Zfa}/froundnx.s.yaml | 0 spec/std/isa/isa/fp.idl | 20 +++++++++++++++++++- 6 files changed, 36 insertions(+), 3 deletions(-) rename spec/std/isa/inst/{F => Zfa}/fli.s.yaml (100%) rename spec/std/isa/inst/{F => Zfa}/fmaxm.s.yaml (100%) rename spec/std/isa/inst/{F => Zfa}/fminm.s.yaml (100%) rename spec/std/isa/inst/{F => Zfa}/fround.s.yaml (57%) rename spec/std/isa/inst/{F => Zfa}/froundnx.s.yaml (100%) diff --git a/spec/std/isa/inst/F/fli.s.yaml b/spec/std/isa/inst/Zfa/fli.s.yaml similarity index 100% rename from spec/std/isa/inst/F/fli.s.yaml rename to spec/std/isa/inst/Zfa/fli.s.yaml diff --git a/spec/std/isa/inst/F/fmaxm.s.yaml b/spec/std/isa/inst/Zfa/fmaxm.s.yaml similarity index 100% rename from spec/std/isa/inst/F/fmaxm.s.yaml rename to spec/std/isa/inst/Zfa/fmaxm.s.yaml diff --git a/spec/std/isa/inst/F/fminm.s.yaml b/spec/std/isa/inst/Zfa/fminm.s.yaml similarity index 100% rename from spec/std/isa/inst/F/fminm.s.yaml rename to spec/std/isa/inst/Zfa/fminm.s.yaml diff --git a/spec/std/isa/inst/F/fround.s.yaml b/spec/std/isa/inst/Zfa/fround.s.yaml similarity index 57% rename from spec/std/isa/inst/F/fround.s.yaml rename to spec/std/isa/inst/Zfa/fround.s.yaml index c1ea46105..9ee95ce2f 100644 --- a/spec/std/isa/inst/F/fround.s.yaml +++ b/spec/std/isa/inst/Zfa/fround.s.yaml @@ -6,9 +6,15 @@ $schema: "inst_schema.json#" kind: instruction name: fround.s -long_name: No synopsis available +long_name: Rounds single-precision float to integer description: | - No description available. + Rounds the single-precision floating-point number in floating-point register _fs1_ to an integer, according to the rounding mode specified in the instruction’s _rm_ field. + + It then writes that integer, represented as a single-precision floating-point number, to floating-point register _fd_. + + Zero and infinite inputs are copied to _fd_ unmodified. + + Signaling NaN inputs cause the invalid operation exception flag to be set; no other exception flags are set. FROUND.S is encoded like FCVT.S.D, but with rs2=4. definedBy: Zfa assembly: fd, fs1, rm encoding: @@ -27,6 +33,15 @@ access: vu: always data_independent_timing: true operation(): | + check_f_ok($encoding); + RoundingMode rounding_mode = rm_to_mode(rm, $encoding); + if ((is_sp_neg_inf?(f[fs1])) || (is_sp_pos_inf?(f[fs1])) || (is_sp_pos_zero?(f[fs1])) + || (is_sp_neg_zero?(f[fs1]))) { + f[fd] = f[fs1]; + } else { + f[fd] = round_f32(f[fs1], rounding_mode); + } + mark_f_state_dirty(); # SPDX-SnippetBegin # SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model diff --git a/spec/std/isa/inst/F/froundnx.s.yaml b/spec/std/isa/inst/Zfa/froundnx.s.yaml similarity index 100% rename from spec/std/isa/inst/F/froundnx.s.yaml rename to spec/std/isa/inst/Zfa/froundnx.s.yaml diff --git a/spec/std/isa/isa/fp.idl b/spec/std/isa/isa/fp.idl index 5ae60bae6..c3267c949 100644 --- a/spec/std/isa/isa/fp.idl +++ b/spec/std/isa/isa/fp.idl @@ -349,7 +349,6 @@ function softfloat_roundToI32 { RoundingMode roundingMode description { Round to signed 32-bit integer, using +rounding_mode+ - Round to signed 32-bit integer, using +rounding_mode+ } body { Bits<16> roundIncrement = 0x800; @@ -1106,3 +1105,22 @@ function f32_to_ui32 { return softfloat_roundToUI32(sign, sig64, mode); } } + +function round_f32 { + returns U32 + arguments + U32 a, + RoundingMode mode + description { + Rounds 32-bit floating point number to a signed 32-bit integer. + This 32-bit integer is represented as a floating point number and returned. + } + body { + # intermediate variable for storing 32-bit rounded integer + U32 intermediate; + # round 32-bit floating point number to integer + intermediate = f32_to_i32(a, mode); + # represent the integer as floating point number + return i32_to_f32(intermediate, mode); + } +} From fcbb9e0affce066fa9a6f1914dc8b20431673ad5 Mon Sep 17 00:00:00 2001 From: Shashank V M Date: Sun, 13 Jul 2025 14:07:03 +0000 Subject: [PATCH 04/11] fix: fround IDL code --- spec/std/isa/inst/Zfa/fround.s.yaml | 7 +- spec/std/isa/isa/fp.idl | 186 +++++++++++++++++++++++++++- 2 files changed, 181 insertions(+), 12 deletions(-) diff --git a/spec/std/isa/inst/Zfa/fround.s.yaml b/spec/std/isa/inst/Zfa/fround.s.yaml index 9ee95ce2f..fbf631e35 100644 --- a/spec/std/isa/inst/Zfa/fround.s.yaml +++ b/spec/std/isa/inst/Zfa/fround.s.yaml @@ -35,12 +35,7 @@ data_independent_timing: true operation(): | check_f_ok($encoding); RoundingMode rounding_mode = rm_to_mode(rm, $encoding); - if ((is_sp_neg_inf?(f[fs1])) || (is_sp_pos_inf?(f[fs1])) || (is_sp_pos_zero?(f[fs1])) - || (is_sp_neg_zero?(f[fs1]))) { - f[fd] = f[fs1]; - } else { - f[fd] = round_f32(f[fs1], rounding_mode); - } + f[fd] = round_f32_to_integral(f[fs1], rounding_mode); mark_f_state_dirty(); # SPDX-SnippetBegin diff --git a/spec/std/isa/isa/fp.idl b/spec/std/isa/isa/fp.idl index c3267c949..e20277966 100644 --- a/spec/std/isa/isa/fp.idl +++ b/spec/std/isa/isa/fp.idl @@ -997,7 +997,6 @@ function i32_to_f32 { RoundingMode mode description { Converts 32-bit signed integer to 32-bit floating point number - Converts 32-bit signed integer to 32-bit floating point number } body { # sign of integer, it is 1 when negative @@ -1017,7 +1016,6 @@ function ui32_to_f32 { RoundingMode mode description { Converts 32-bit unsigned integer to 32-bit floating point number - Converts 32-bit unsigned integer to 32-bit floating point number } body { # sign of integer, it is 1 when negative @@ -1106,7 +1104,175 @@ function f32_to_ui32 { } } -function round_f32 { +function softfloat_roundPackToF32_no_flag { + returns Bits<32> # single precision value + arguments + Bits<1> sign, + Bits<8> exp, + Bits<23> sig, + RoundingMode mode + description { + Round FP value according to +mdode+ and then pack it in IEEE format. + No flags to be set + } + body { + Bits<8> roundIncrement = 0x40; + if ( (mode != RoundingMode::RNE) && (mode != RoundingMode::RMM)) { + roundIncrement = + (mode == ((sign != 0) ? RoundingMode::RDN : RoundingMode::RUP)) + ? 0x7F + : 0; + } + Bits<8> roundBits = sig & 0x7f; + + if ( 0xFD <= exp ) { + if ($signed(exp) < 's0) { + Boolean isTiny = + ($signed(exp) < -8's1) || (sig + roundIncrement < 0x80000000); + sig = softfloat_shiftRightJam32( sig, -exp ); + exp = 0; + roundBits = sig & 0x7F; + } else if ('shFD < $signed(exp) || (0x80000000 <= sig + roundIncrement)) { + return packToF32UI(sign, 0xFF, 0) - ((roundIncrement == 0) ? 1 : 0); + } + } + + sig = (sig + roundIncrement) >> 7; + sig = sig & ~((roundBits ^ 0x40) & ((mode == RoundingMode::RNE) ? 1 : 0)); + if ( sig == 0 ) { + exp = 0; + } + return packToF32UI(sign, exp, sig); + } +} + +function softfloat_normRoundPackToF32_no_flag { + returns Bits<32> + arguments + Bits<1> sign, + Bits<8> exp, + Bits<23> sig, + RoundingMode mode + description { + Normalize, round, and pack into a 32-bit floating point value + No flags to be set + } + body { + Bits<8> shiftDist = count_leading_zeros<32>(sig) - 1; + exp = exp - shiftDist; + if ((7 <= shiftDist) && (exp < 0xFD)) { + return packToF32UI(sign, (sig != 0) ? exp : 0, sig << (shiftDist - 7)); + } else { + return softfloat_roundPackToF32_no_flag(sign, exp, sig << shiftDist, mode); + } + } +} + +function i32_to_f32_no_flag { + returns U32 + arguments + U32 a, + RoundingMode mode + description { + Converts 32-bit signed integer to 32-bit floating point number + No flags to be set + } + body { + # sign of integer, it is 1 when negative + Bits<1> sign = a[31]; + if ((a & 0x7FFFFFFF) == 0) { + return (sign == 1) ? packToF32UI(1, 0x9E, 0) : packToF32UI(0, 0, 0); + } + U32 magnitude_of_A = returnMag(a); + return softfloat_normRoundPackToF32_no_flag(sign, 0x9C, magnitude_of_A, mode); + } +} + +function softfloat_roundToI32_no_flag { + returns Bits<32> + arguments + Bits<1> sign, + Bits<64> sig, + RoundingMode roundingMode + description { + Round to signed 32-bit integer, using +rounding_mode+ + No flag to be set + } + body { + Bits<16> roundIncrement = 0x800; + if ( + (roundingMode != RoundingMode::RMM) + && (roundingMode != RoundingMode::RNE) + ) { + roundIncrement = 0; + if ( + sign == 1 + ? (roundingMode == RoundingMode::RDN) + : (roundingMode == RoundingMode::RUP) + ) { + roundIncrement = 0xFFF; + } + } + Bits<16> roundBits = sig & 0xFFF; + sig = sig + roundIncrement; + if ((sig & 0xFFFFF00000000000) != 0) { + return sign == 1 ? WORD_NEG_OVERFLOW : WORD_POS_OVERFLOW; + } + + Bits<32> sig32 = sig >> 12; + if ( + (roundBits == 0x800 && (roundingMode == RoundingMode::RNE)) + ) { + sig32 = sig32 & ~32'b1; + } + + Bits<32> z = (sign == 1) ? -sig32 : sig32; + if ((z != 0) && (($signed(z) < 's0) != (sign == 1))) { + return sign == 1 ? WORD_NEG_OVERFLOW : WORD_POS_OVERFLOW; + } + + return z; + } +} + +function f32_to_i32_no_flag { + returns U32 + arguments + U32 a, + RoundingMode mode + description { + Converts 32-bit floating point number to a signed 32-bit integer + No flags to be set + } + body { + Bits<1> sign = signF32UI(a); + Bits<8> exp = expF32UI(a); + Bits<23> sig = fracF32UI(a); + Bits<8> shiftDist; + U64 sig64; + # for NaN return the highest positive value and set floating-point flag to invalid. + if ((exp == 8'hFF) && (sig != 0)) { + sign = 0; + return I32_NAN; + } + + # MSB of significand is set to 1 because minimum 32-bit integer in IEEE 754 is 32'h80000000 + if (exp != 0) { + sig = sig | 32'h00800000; + } + + sig64 = sig << 32; + shiftDist = 8'hAA - exp; + + if (shiftDist > 0) { + sig64 = softfloat_shiftRightJam64( sig64, shiftDist); + } + + return softfloat_roundToI32_no_flag(sign, sig64, mode); + } +} + +function round_f32_to_integral { returns U32 arguments U32 a, @@ -1116,11 +1282,19 @@ function round_f32 { This 32-bit integer is represented as a floating point number and returned. } body { + if ((is_sp_neg_inf?(a)) || (is_sp_pos_inf?(a)) || (is_sp_pos_zero?(a)) || (is_sp_neg_zero?(a))) { + # Return zero or infinity respectively for zero or infinity inputs + return a; + } else if is_sp_signaling_nan?(a) { + # set invalid flag for signaling NaN + set_fp_flag(FpFlag::NV); + return a; + } # intermediate variable for storing 32-bit rounded integer U32 intermediate; - # round 32-bit floating point number to integer - intermediate = f32_to_i32(a, mode); + # round 32-bit floating point number to integer, no flags to be set + intermediate = f32_to_i32_no_flag(a, mode); # represent the integer as floating point number - return i32_to_f32(intermediate, mode); + return i32_to_f32_no_flag(intermediate, mode); } } From 6a225d55d3d1b02468c0c85fa2b739a46ec9b2bb Mon Sep 17 00:00:00 2001 From: Shashank V M Date: Sun, 13 Jul 2025 14:55:45 +0000 Subject: [PATCH 05/11] fix: syntax error in IDL code --- spec/std/isa/isa/fp.idl | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/spec/std/isa/isa/fp.idl b/spec/std/isa/isa/fp.idl index e20277966..a438f30ce 100644 --- a/spec/std/isa/isa/fp.idl +++ b/spec/std/isa/isa/fp.idl @@ -461,10 +461,16 @@ function softfloat_roundToUI32 { ) { roundIncrement = 0; if ( sign == 1) { - if (sig == 0) return 0; - if (roundingMode == RoundingMode::RDN) set_fp_flag(FpFlag::NV); + if (sig == 0) { + return 0; + } + if (roundingMode == RoundingMode::RDN) { + set_fp_flag(FpFlag::NV); + } } else { - if (roundingMode == RoundingMode::RUP) roundIncrement = 0xFFF; + if (roundingMode == RoundingMode::RUP) { + roundIncrement = 0xFFF; + } } } @@ -1056,7 +1062,7 @@ function f32_to_i32 { sig = sig | 32'h00800000; } - sig64 = sig << 32; + sig64 = sig `<< 32; shiftDist = 8'hAA - exp; if (shiftDist > 0) { @@ -1093,7 +1099,7 @@ function f32_to_ui32 { sig = sig | 32'h00800000; } - sig64 = sig << 32; + sig64 = sig `<< 32; shiftDist = 8'hAA - exp; if (shiftDist > 0) { @@ -1261,7 +1267,7 @@ function f32_to_i32_no_flag { sig = sig | 32'h00800000; } - sig64 = sig << 32; + sig64 = sig `<< 32; shiftDist = 8'hAA - exp; if (shiftDist > 0) { @@ -1285,7 +1291,7 @@ function round_f32_to_integral { if ((is_sp_neg_inf?(a)) || (is_sp_pos_inf?(a)) || (is_sp_pos_zero?(a)) || (is_sp_neg_zero?(a))) { # Return zero or infinity respectively for zero or infinity inputs return a; - } else if is_sp_signaling_nan?(a) { + } else if (is_sp_signaling_nan?(a)) { # set invalid flag for signaling NaN set_fp_flag(FpFlag::NV); return a; From 1566e311ef3a24aa80ed1c7deb844bbcc91f3516 Mon Sep 17 00:00:00 2001 From: Shashank V M Date: Sun, 13 Jul 2025 15:00:29 +0000 Subject: [PATCH 06/11] fix: removed duplicate word --- spec/std/isa/isa/fp.idl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/spec/std/isa/isa/fp.idl b/spec/std/isa/isa/fp.idl index a438f30ce..698f6499d 100644 --- a/spec/std/isa/isa/fp.idl +++ b/spec/std/isa/isa/fp.idl @@ -23,8 +23,8 @@ Bits<32> SP_NEG_ZERO = 32'b1_00000000_00000000000000000000000; Bits<32> SP_CANONICAL_NAN = 32'b0_11111111_10000000000000000000000; Bits<16> HP_CANONICAL_NAN = 16'b0_11111_1000000000; -Bits<32> WORD_NEG_OVERFLOW = 32'h8000_0000; # minimum signed signed 32-bit integer -Bits<32> WORD_POS_OVERFLOW = 32'h7FFF_FFFF; # maximum signed signed 32-bit integer +Bits<32> WORD_NEG_OVERFLOW = 32'h8000_0000; # minimum signed 32-bit integer +Bits<32> WORD_POS_OVERFLOW = 32'h7FFF_FFFF; # maximum signed 32-bit integer Bits<32> UI32_NEG_OVERFLOW = 32'h0000_0000; # minimum unsigned 32-bit integer Bits<32> UI32_POS_OVERFLOW = 32'hFFFF_FFFF; # maximum unsigned 32-bit integer From 1b6fc0cafdd2bf50528224f2a44a2051574d9a7f Mon Sep 17 00:00:00 2001 From: Shashank V M Date: Sun, 13 Jul 2025 21:02:31 +0530 Subject: [PATCH 07/11] fix: fp.idl Remove duplicated lines that got added by mistake Signed-off-by: Shashank V M --- spec/std/isa/isa/fp.idl | 8 -------- 1 file changed, 8 deletions(-) diff --git a/spec/std/isa/isa/fp.idl b/spec/std/isa/isa/fp.idl index 698f6499d..e4aacbd7a 100644 --- a/spec/std/isa/isa/fp.idl +++ b/spec/std/isa/isa/fp.idl @@ -32,14 +32,6 @@ Bits<32> UI32_POS_OVERFLOW = 32'hFFFF_FFFF; # maximum unsigned 32-bit integer Bits<32> UI32_NAN = 32'hFFFF_FFFF; # NaN to unsigned 32-bit integer Bits<32> I32_NAN = 32'h7FFF_FFFF; # NaN to signed 32-bit integer - -Bits<32> UI32_NEG_OVERFLOW = 32'h0000_0000; # minimum unsigned 32-bit integer -Bits<32> UI32_POS_OVERFLOW = 32'hFFFF_FFFF; # maximum unsigned 32-bit integer - -Bits<32> UI32_NAN = 32'hFFFF_FFFF; # NaN to unsigned 32-bit integer -Bits<32> I32_NAN = 32'h7FFF_FFFF; # NaN to signed 32-bit integer - - enum RoundingMode { RNE 0b000 # Round to Nearest, ties to Even RTZ 0b001 # Round toward Zero From 6d4145e11b05b8ce0033d457ff08eee28eecb629 Mon Sep 17 00:00:00 2001 From: Shashank V M Date: Sun, 13 Jul 2025 21:14:24 +0530 Subject: [PATCH 08/11] fix: fp.idl Signed-off-by: Shashank V M --- spec/std/isa/isa/fp.idl | 60 ----------------------------------------- 1 file changed, 60 deletions(-) diff --git a/spec/std/isa/isa/fp.idl b/spec/std/isa/isa/fp.idl index e4aacbd7a..1dcfe70b9 100644 --- a/spec/std/isa/isa/fp.idl +++ b/spec/std/isa/isa/fp.idl @@ -422,66 +422,6 @@ function softfloat_roundToUI32 { z = z & ~32'b1; } - - - if ((z != 0) && (sign == 1)) { - set_fp_flag(FpFlag::NV); - return sign == 1 ? UI32_NEG_OVERFLOW : UI32_POS_OVERFLOW; - } - - if (roundBits != 0) { - set_fp_flag(FpFlag::NX); - } - return z; - } -} - -function softfloat_roundToUI32 { - returns Bits<32> - arguments - Bits<1> sign, - Bits<64> sig, - RoundingMode roundingMode - description { - Round to unsigned 32-bit integer, using +rounding_mode+ - } - body { - Bits<16> roundIncrement = 0x800; - if ( - (roundingMode != RoundingMode::RMM) - && (roundingMode != RoundingMode::RNE) - ) { - roundIncrement = 0; - if ( sign == 1) { - if (sig == 0) { - return 0; - } - if (roundingMode == RoundingMode::RDN) { - set_fp_flag(FpFlag::NV); - } - } else { - if (roundingMode == RoundingMode::RUP) { - roundIncrement = 0xFFF; - } - } - } - - Bits<16> roundBits = sig & 0xFFF; - sig = sig + roundIncrement; - if ((sig & 0xFFFFF00000000000) != 0) { - set_fp_flag(FpFlag::NV); - return sign == 1 ? UI32_NEG_OVERFLOW : UI32_POS_OVERFLOW; - } - - Bits<32> z = sig >> 12; - if ( - (roundBits == 0x800 && (roundingMode == RoundingMode::RNE)) - ) { - z = z & ~32'b1; - } - - - if ((z != 0) && (sign == 1)) { set_fp_flag(FpFlag::NV); return sign == 1 ? UI32_NEG_OVERFLOW : UI32_POS_OVERFLOW; From 665f2c6166067fb47d2481c81a023b7fcc8f5d6b Mon Sep 17 00:00:00 2001 From: Shashank V M Date: Sun, 13 Jul 2025 15:51:49 +0000 Subject: [PATCH 09/11] ci: update golden instruction appendix --- .../all_instructions.golden.adoc | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/backends/instructions_appendix/all_instructions.golden.adoc b/backends/instructions_appendix/all_instructions.golden.adoc index c1e8d2fd9..576d759d5 100644 --- a/backends/instructions_appendix/all_instructions.golden.adoc +++ b/backends/instructions_appendix/all_instructions.golden.adoc @@ -1,6 +1,6 @@ = Instruction Appendix :doctype: book -:wavedrom: /workspace/riscv-unified-db/node_modules/.bin/wavedrom-cli +:wavedrom: /workspaces/riscv-unified-db/node_modules/.bin/wavedrom-cli // Now the document header is complete and the wavedrom attribute is active. @@ -12951,7 +12951,7 @@ Included in:: == fround.s Synopsis:: -No synopsis available +Rounds single-precision float to integer Assembly:: fround.s fd, fs1, rm @@ -12963,7 +12963,13 @@ Encoding:: .... Description:: -No description available. +Rounds the single-precision floating-point number in floating-point register _fs1_ to an integer, according to the rounding mode specified in the instruction’s _rm_ field. + +It then writes that integer, represented as a single-precision floating-point number, to floating-point register _fd_. + +Zero and infinite inputs are copied to _fd_ unmodified. + +Signaling NaN inputs cause the invalid operation exception flag to be set; no other exception flags are set. FROUND.S is encoded like FCVT.S.D, but with rs2=4. Decode Variables:: From a55a639b794ee8e0520c095aa877b4ada58a3627 Mon Sep 17 00:00:00 2001 From: Shashank V M Date: Wed, 16 Jul 2025 04:23:05 +0000 Subject: [PATCH 10/11] fix: apply Paul's suggested change --- spec/std/isa/inst/Zfa/fround.s.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/std/isa/inst/Zfa/fround.s.yaml b/spec/std/isa/inst/Zfa/fround.s.yaml index fbf631e35..a6252bfdd 100644 --- a/spec/std/isa/inst/Zfa/fround.s.yaml +++ b/spec/std/isa/inst/Zfa/fround.s.yaml @@ -6,7 +6,7 @@ $schema: "inst_schema.json#" kind: instruction name: fround.s -long_name: Rounds single-precision float to integer +long_name: Floating-point round single-precision float to integer description: | Rounds the single-precision floating-point number in floating-point register _fs1_ to an integer, according to the rounding mode specified in the instruction’s _rm_ field. From e4f0b9d40c6a56857d967c243a7237791e6a9920 Mon Sep 17 00:00:00 2001 From: Shashank V M Date: Wed, 16 Jul 2025 06:40:40 +0000 Subject: [PATCH 11/11] ci: update golden instruction appendix --- backends/instructions_appendix/all_instructions.golden.adoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backends/instructions_appendix/all_instructions.golden.adoc b/backends/instructions_appendix/all_instructions.golden.adoc index 576d759d5..81390c170 100644 --- a/backends/instructions_appendix/all_instructions.golden.adoc +++ b/backends/instructions_appendix/all_instructions.golden.adoc @@ -12951,7 +12951,7 @@ Included in:: == fround.s Synopsis:: -Rounds single-precision float to integer +Floating-point round single-precision float to integer Assembly:: fround.s fd, fs1, rm