Skip to content

Commit 014a1dc

Browse files
authored
Add IDL for converting 32-bit Floating point number to 32-bit signed and unsigned integer (#756)
Added IDL code, descriptions and long names. --------- Signed-off-by: Shashank V M <shashankmathew8@gmail.com> Signed-off-by: Shashank V M <svivekan@qti.qualcomm.com>
1 parent f62cbc1 commit 014a1dc

File tree

4 files changed

+216
-49
lines changed

4 files changed

+216
-49
lines changed

arch/inst/F/fcvt.w.s.yaml

Lines changed: 6 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,10 @@
33
$schema: "inst_schema.json#"
44
kind: instruction
55
name: fcvt.w.s
6-
long_name: Convert single-precision float to integer word to signed 32-bit integer
6+
long_name: Convert single-precision float to signed word.
77
description: |
8-
Converts a floating-point number in floating-point register _fs1_ to a signed 32-bit integer indicates
9-
integer register _rd_.
8+
Converts a floating-point number in floating-point register _fs1_ to a signed 32-bit integer in
9+
integer register _xd_.
1010
1111
For XLEN &gt;32, `fcvt.w.s` sign-extends the 32-bit result to the destination register width.
1212
@@ -30,7 +30,7 @@ description: |
3030
All floating-point to integer and integer to floating-point conversion instructions round
3131
according to the _rm_ field.
3232
A floating-point register can be initialized to floating-point positive zero using
33-
`fcvt.s.w rd, x0`, which will never set any exception flags.
33+
`fcvt.s.w xd, x0`, which will never set any exception flags.
3434
3535
All floating-point conversion instructions set the Inexact exception flag if the rounded
3636
result differs from the operand value and the Invalid exception flag is not set.
@@ -44,7 +44,7 @@ encoding:
4444
location: 19-15
4545
- name: rm
4646
location: 14-12
47-
- name: rd
47+
- name: xd
4848
location: 11-7
4949
access:
5050
s: always
@@ -54,30 +54,8 @@ access:
5454
data_independent_timing: true
5555
operation(): |
5656
check_f_ok($encoding);
57-
58-
Bits<32> sp_value = f[fs1][31:0];
59-
60-
Bits<1> sign = sp_value[31];
61-
Bits<8> exp = sp_value[30:23];
62-
Bits<23> sig = sp_value[22:0];
63-
6457
RoundingMode rounding_mode = rm_to_mode(rm, $encoding);
65-
66-
if ( (exp == 0xff) && (sig != 0)) {
67-
sign = 0;
68-
set_fp_flag(FpFlag::NV);
69-
X[rd] = SP_CANONICAL_NAN;
70-
} else {
71-
if (exp != 0) {
72-
sig = sig | 0x00800000;
73-
}
74-
Bits<64> sig64 = sig << 32;
75-
Bits<16> shift_dist = 0xAA - exp;
76-
if (0 < shift_dist) {
77-
sig64 = softfloat_shiftRightJam64(sig64, shift_dist );
78-
}
79-
X[rd] = softfloat_roundToI32( sign, sig64, rounding_mode );
80-
}
58+
X[xd] = f32_to_i32(X[fs1], rounding_mode);
8159
8260
# SPDX-SnippetBegin
8361
# SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model <https://github.com/riscv/sail-riscv/blob/master/LICENCE>

arch/inst/F/fcvt.wu.s.yaml

Lines changed: 34 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,19 +3,46 @@
33
$schema: "inst_schema.json#"
44
kind: instruction
55
name: fcvt.wu.s
6-
long_name: No synopsis available
6+
long_name: Convert single-precision float to unsigned word.
77
description: |
8-
No description available.
8+
Converts a floating-point number in floating-point register _fs1_ to an unsigned 32-bit integer in integer register _xd_.
9+
10+
For XLEN &gt;32, `fcvt.wu.s` sign-extends the 32-bit result to the destination register width.
11+
12+
If the rounded result is not representable as a 32-bit unsigned integer, it is clipped to the
13+
nearest value and the invalid flag is set.
14+
15+
The range of valid inputs and behavior for invalid inputs are:
16+
17+
[separator="!"]
18+
!===
19+
! ! Value
20+
21+
h! Minimum valid input (after rounding) ! `0`
22+
h! Maximum valid input (after rounding) ! `2^32 - 1`
23+
h! Output for out-of-range negative input ! `0`
24+
h! Output for `-&infin;` ! `0`
25+
h! Output for out-of-range positive input ! `2^32 - 1`
26+
h! Output for `+&infin;` for `NaN` ! `2^32 - 1`
27+
!===
28+
29+
All floating-point to integer and integer to floating-point conversion instructions round
30+
according to the _rm_ field.
31+
A floating-point register can be initialized to floating-point positive zero using
32+
`fcvt.s.w xd, x0`, which will never set any exception flags.
33+
34+
All floating-point conversion instructions set the Inexact exception flag if the rounded
35+
result differs from the operand value and the Invalid exception flag is not set.
936
definedBy: F
1037
assembly: xd, fs1, rm
1138
encoding:
1239
match: 110000000001-------------1010011
1340
variables:
14-
- name: rs1
41+
- name: fs1
1542
location: 19-15
1643
- name: rm
1744
location: 14-12
18-
- name: rd
45+
- name: xd
1946
location: 11-7
2047
access:
2148
s: always
@@ -24,7 +51,9 @@ access:
2451
vu: always
2552
data_independent_timing: true
2653
operation(): |
27-
54+
check_f_ok($encoding);
55+
RoundingMode rounding_mode = rm_to_mode(rm, $encoding);
56+
X[xd] = f32_to_ui32(X[fs1], rounding_mode);
2857
# SPDX-SnippetBegin
2958
# SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model <https://github.com/riscv/sail-riscv/blob/master/LICENCE>
3059
# SPDX-License-Identifier: BSD-2-Clause

arch/isa/fp.idl

Lines changed: 138 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,15 @@ Bits<32> SP_NEG_ZERO = 32'b1_00000000_00000000000000000000000;
2020
Bits<32> SP_CANONICAL_NAN = 32'b0_11111111_10000000000000000000000;
2121
Bits<16> HP_CANONICAL_NAN = 16'b0_11111_1000000000;
2222

23-
Bits<32> WORD_NEG_OVERFLOW = 32'h8000_0000; # minimum 32-bit integer
24-
Bits<32> WORD_POS_OVERFLOW = 32'h7FFF_FFFF; # maximum 32-bit integer
23+
Bits<32> WORD_NEG_OVERFLOW = 32'h8000_0000; # minimum signed 32-bit integer
24+
Bits<32> WORD_POS_OVERFLOW = 32'h7FFF_FFFF; # maximum signed 32-bit integer
25+
26+
Bits<32> UI32_NEG_OVERFLOW = 32'h0000_0000; # minimum unsigned 32-bit integer
27+
Bits<32> UI32_POS_OVERFLOW = 32'hFFFF_FFFF; # maximum unsigned 32-bit integer
28+
29+
Bits<32> UI32_NAN = 32'hFFFF_FFFF; # NaN to unsigned 32-bit integer
30+
Bits<32> I32_NAN = 32'h7FFF_FFFF; # NaN to signed 32-bit integer
31+
2532

2633
enum RoundingMode {
2734
RNE 0b000 # Round to Nearest, ties to Even
@@ -331,7 +338,7 @@ function softfloat_roundToI32 {
331338
Bits<64> sig,
332339
RoundingMode roundingMode
333340
description {
334-
Round to unsigned 32-bit integer, using +rounding_mode+
341+
Round to signed 32-bit integer, using +rounding_mode+
335342
}
336343
body {
337344
Bits<16> roundIncrement = 0x800;
@@ -375,6 +382,58 @@ function softfloat_roundToI32 {
375382
}
376383
}
377384

385+
function softfloat_roundToUI32 {
386+
returns Bits<32>
387+
arguments
388+
Bits<1> sign,
389+
Bits<64> sig,
390+
RoundingMode roundingMode
391+
description {
392+
Round to unsigned 32-bit integer, using +rounding_mode+
393+
}
394+
body {
395+
Bits<16> roundIncrement = 0x800;
396+
if (
397+
(roundingMode != RoundingMode::RMM)
398+
&& (roundingMode != RoundingMode::RNE)
399+
) {
400+
roundIncrement = 0;
401+
if ( sign == 1) {
402+
if (sig == 0) { return 0; }
403+
if (roundingMode == RoundingMode::RDN) { set_fp_flag(FpFlag::NV); }
404+
} else {
405+
if (roundingMode == RoundingMode::RUP) { roundIncrement = 0xFFF; }
406+
}
407+
}
408+
409+
Bits<16> roundBits = sig & 0xFFF;
410+
sig = sig + roundIncrement;
411+
if ((sig & 0xFFFFF00000000000) != 0) {
412+
set_fp_flag(FpFlag::NV);
413+
return sign == 1 ? UI32_NEG_OVERFLOW : UI32_POS_OVERFLOW;
414+
}
415+
416+
Bits<32> z = sig >> 12;
417+
if (
418+
(roundBits == 0x800 && (roundingMode == RoundingMode::RNE))
419+
) {
420+
z = z & ~32'b1;
421+
}
422+
423+
424+
425+
if ((z != 0) && (sign == 1)) {
426+
set_fp_flag(FpFlag::NV);
427+
return sign == 1 ? UI32_NEG_OVERFLOW : UI32_POS_OVERFLOW;
428+
}
429+
430+
if (roundBits != 0) {
431+
set_fp_flag(FpFlag::NX);
432+
}
433+
return z;
434+
}
435+
}
436+
378437
function packToF32UI {
379438
returns Bits<32>
380439
arguments
@@ -875,7 +934,7 @@ function i32_to_f32 {
875934
U32 a,
876935
RoundingMode mode
877936
description {
878-
Converts 32-bit signed integer to 32-bit floating point
937+
Converts 32-bit signed integer to 32-bit floating point number
879938
}
880939
body {
881940
# sign of integer, it is 1 when negative
@@ -894,7 +953,7 @@ function ui32_to_f32 {
894953
U32 a,
895954
RoundingMode mode
896955
description {
897-
Converts 32-bit unsigned integer to 32-bit floating point
956+
Converts 32-bit unsigned integer to 32-bit floating point number
898957
}
899958
body {
900959
# sign of integer, it is 1 when negative
@@ -908,3 +967,77 @@ function ui32_to_f32 {
908967
}
909968
}
910969
}
970+
971+
function f32_to_i32 {
972+
returns U32
973+
arguments
974+
U32 a,
975+
RoundingMode mode
976+
description {
977+
Converts 32-bit floating point number to a signed 32-bit integer
978+
}
979+
body {
980+
Bits<1> sign = signF32UI(a);
981+
Bits<8> exp = expF32UI(a);
982+
Bits<23> sig = fracF32UI(a);
983+
Bits<8> shiftDist;
984+
U64 sig64;
985+
# for NaN return the highest positive value and set floating-point flag to invalid.
986+
if ((exp == 8'hFF) && (sig != 0)) {
987+
sign = 0;
988+
set_fp_flag(FpFlag::NV);
989+
return I32_NAN;
990+
}
991+
992+
# MSB of significand is set to 1 because minimum 32-bit integer in IEEE 754 is 32'h80000000
993+
if (exp != 0) {
994+
sig = sig | 32'h00800000;
995+
}
996+
997+
sig64 = sig `<< 32;
998+
shiftDist = 8'hAA - exp;
999+
1000+
if (shiftDist > 0) {
1001+
sig64 = softfloat_shiftRightJam64( sig64, shiftDist);
1002+
}
1003+
1004+
return softfloat_roundToI32(sign, sig64, mode);
1005+
}
1006+
}
1007+
1008+
function f32_to_ui32 {
1009+
returns U32
1010+
arguments
1011+
U32 a,
1012+
RoundingMode mode
1013+
description {
1014+
Converts 32-bit floating point number to an unsigned 32-bit integer
1015+
}
1016+
body {
1017+
Bits<1> sign = signF32UI(a);
1018+
Bits<8> exp = expF32UI(a);
1019+
Bits<23> sig = fracF32UI(a);
1020+
Bits<8> shiftDist;
1021+
U64 sig64;
1022+
# for NaN return the highest positive value and set floating-point flag to invalid.
1023+
if ((exp == 8'hFF) && (sig != 0)) {
1024+
sign = 0;
1025+
set_fp_flag(FpFlag::NV);
1026+
return UI32_NAN;
1027+
}
1028+
1029+
# MSB of significand is set to 1 because minimum 32-bit integer in IEEE 754 is 32'h80000000
1030+
if (exp != 0) {
1031+
sig = sig | 32'h00800000;
1032+
}
1033+
1034+
sig64 = sig `<< 32;
1035+
shiftDist = 8'hAA - exp;
1036+
1037+
if (shiftDist > 0) {
1038+
sig64 = softfloat_shiftRightJam64( sig64, shiftDist);
1039+
}
1040+
1041+
return softfloat_roundToUI32(sign, sig64, mode);
1042+
}
1043+
}

0 commit comments

Comments
 (0)