Skip to content

Add IDL code for fround instruction #896

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 23 commits into from
Jul 16, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
1fcf414
Add function to convert a Floating point number to 32-bit integer
ShashankVM May 8, 2025
d5aef83
Merge branch 'main' of https://github.com/ShashankVM/riscv-unified-db
ShashankVM May 9, 2025
15b98dd
Merge remote-tracking branch 'upstream/main'
ShashankVM May 9, 2025
461a007
Add IDL for converting 32-bit Floating point number to 32-bit signed …
ShashankVM May 9, 2025
1de3144
Merge branch 'riscv-software-src:main' into main
ShashankVM May 15, 2025
6b2e852
Merge branch 'riscv-software-src:main' into main
ShashankVM May 20, 2025
6696956
Merge branch 'riscv-software-src:main' into main
ShashankVM May 22, 2025
aaa08c2
Merge branch 'riscv-software-src:main' into main
ShashankVM May 23, 2025
30ace11
Merge branch 'riscv-software-src:main' into main
ShashankVM May 25, 2025
19f1f2e
chore: merge branch
ShashankVM Jun 4, 2025
60f6a6e
Merge branch 'main' of https://github.com/ShashankVM/riscv-unified-db
ShashankVM Jun 4, 2025
0241ff8
Merge branch 'main' of https://github.com/ShashankVM/riscv-unified-db
ShashankVM Jul 13, 2025
2dd062f
fix: move files to Zfa folder
ShashankVM Jul 13, 2025
fcbb9e0
fix: fround IDL code
ShashankVM Jul 13, 2025
6a225d5
fix: syntax error in IDL code
ShashankVM Jul 13, 2025
1566e31
fix: removed duplicate word
ShashankVM Jul 13, 2025
1b6fc0c
fix: fp.idl
ShashankVM Jul 13, 2025
6d4145e
fix: fp.idl
ShashankVM Jul 13, 2025
665f2c6
ci: update golden instruction appendix
ShashankVM Jul 13, 2025
a55a639
fix: apply Paul's suggested change
ShashankVM Jul 16, 2025
de3c446
Merge branch 'main' into main
ShashankVM Jul 16, 2025
e4f0b9d
ci: update golden instruction appendix
ShashankVM Jul 16, 2025
b618724
Merge branch 'main' into main
ShashankVM Jul 16, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 9 additions & 3 deletions backends/instructions_appendix/all_instructions.golden.adoc
Original file line number Diff line number Diff line change
@@ -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.


Expand Down Expand Up @@ -12951,7 +12951,7 @@ Included in::
== fround.s

Synopsis::
No synopsis available
Floating-point round single-precision float to integer

Assembly::
fround.s fd, fs1, rm
Expand All @@ -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::
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,15 @@
$schema: "inst_schema.json#"
kind: instruction
name: fround.s
long_name: No synopsis available
long_name: Floating-point round 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:
Expand All @@ -27,6 +33,10 @@ access:
vu: always
data_independent_timing: true
operation(): |
check_f_ok($encoding);
RoundingMode rounding_mode = rm_to_mode(rm, $encoding);
f[fd] = round_f32_to_integral(f[fs1], rounding_mode);
mark_f_state_dirty();

# SPDX-SnippetBegin
# SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model <https://github.com/riscv/sail-riscv/blob/master/LICENCE>
Expand Down
198 changes: 195 additions & 3 deletions spec/std/isa/isa/fp.idl
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +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


enum RoundingMode {
RNE 0b000 # Round to Nearest, ties to Even
RTZ 0b001 # Round toward Zero
Expand Down Expand Up @@ -423,8 +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;
Expand Down Expand Up @@ -1044,3 +1041,198 @@ function f32_to_ui32 {
return softfloat_roundToUI32(sign, sig64, mode);
}
}

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,
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 {
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, no flags to be set
intermediate = f32_to_i32_no_flag(a, mode);
# represent the integer as floating point number
return i32_to_f32_no_flag(intermediate, mode);
}
}
Loading