Skip to content

Commit 38fe438

Browse files
authored
Add IDL code for fround instruction (#896)
This PR adds IDL code for fround instruction in Zfa folder. --------- Signed-off-by: Shashank V M <svivekan@qti.qualcomm.com>
1 parent 33454f5 commit 38fe438

File tree

7 files changed

+216
-8
lines changed

7 files changed

+216
-8
lines changed

backends/instructions_appendix/all_instructions.golden.adoc

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
= Instruction Appendix
22
:doctype: book
3-
:wavedrom: /workspace/riscv-unified-db/node_modules/.bin/wavedrom-cli
3+
:wavedrom: /workspaces/riscv-unified-db/node_modules/.bin/wavedrom-cli
44
// Now the document header is complete and the wavedrom attribute is active.
55

66

@@ -12951,7 +12951,7 @@ Included in::
1295112951
== fround.s
1295212952

1295312953
Synopsis::
12954-
No synopsis available
12954+
Floating-point round single-precision float to integer
1295512955

1295612956
Assembly::
1295712957
fround.s fd, fs1, rm
@@ -12963,7 +12963,13 @@ Encoding::
1296312963
....
1296412964

1296512965
Description::
12966-
No description available.
12966+
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.
12967+
12968+
It then writes that integer, represented as a single-precision floating-point number, to floating-point register _fd_.
12969+
12970+
Zero and infinite inputs are copied to _fd_ unmodified.
12971+
12972+
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.
1296712973

1296812974

1296912975
Decode Variables::
File renamed without changes.
File renamed without changes.
File renamed without changes.

spec/std/isa/inst/F/fround.s.yaml renamed to spec/std/isa/inst/Zfa/fround.s.yaml

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,15 @@
66
$schema: "inst_schema.json#"
77
kind: instruction
88
name: fround.s
9-
long_name: No synopsis available
9+
long_name: Floating-point round single-precision float to integer
1010
description: |
11-
No description available.
11+
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.
12+
13+
It then writes that integer, represented as a single-precision floating-point number, to floating-point register _fd_.
14+
15+
Zero and infinite inputs are copied to _fd_ unmodified.
16+
17+
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.
1218
definedBy: Zfa
1319
assembly: fd, fs1, rm
1420
encoding:
@@ -27,6 +33,10 @@ access:
2733
vu: always
2834
data_independent_timing: true
2935
operation(): |
36+
check_f_ok($encoding);
37+
RoundingMode rounding_mode = rm_to_mode(rm, $encoding);
38+
f[fd] = round_f32_to_integral(f[fs1], rounding_mode);
39+
mark_f_state_dirty();
3040
3141
# SPDX-SnippetBegin
3242
# SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model <https://github.com/riscv/sail-riscv/blob/master/LICENCE>

spec/std/isa/isa/fp.idl

Lines changed: 195 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@ Bits<32> UI32_POS_OVERFLOW = 32'hFFFF_FFFF; # maximum unsigned 32-bit integer
3232
Bits<32> UI32_NAN = 32'hFFFF_FFFF; # NaN to unsigned 32-bit integer
3333
Bits<32> I32_NAN = 32'h7FFF_FFFF; # NaN to signed 32-bit integer
3434

35-
3635
enum RoundingMode {
3736
RNE 0b000 # Round to Nearest, ties to Even
3837
RTZ 0b001 # Round toward Zero
@@ -423,8 +422,6 @@ function softfloat_roundToUI32 {
423422
z = z & ~32'b1;
424423
}
425424

426-
427-
428425
if ((z != 0) && (sign == 1)) {
429426
set_fp_flag(FpFlag::NV);
430427
return sign == 1 ? UI32_NEG_OVERFLOW : UI32_POS_OVERFLOW;
@@ -1044,3 +1041,198 @@ function f32_to_ui32 {
10441041
return softfloat_roundToUI32(sign, sig64, mode);
10451042
}
10461043
}
1044+
1045+
function softfloat_roundPackToF32_no_flag {
1046+
returns Bits<32> # single precision value
1047+
arguments
1048+
Bits<1> sign,
1049+
Bits<8> exp,
1050+
Bits<23> sig,
1051+
RoundingMode mode
1052+
description {
1053+
Round FP value according to +mdode+ and then pack it in IEEE format.
1054+
No flags to be set
1055+
}
1056+
body {
1057+
Bits<8> roundIncrement = 0x40;
1058+
if ( (mode != RoundingMode::RNE) && (mode != RoundingMode::RMM)) {
1059+
roundIncrement =
1060+
(mode == ((sign != 0) ? RoundingMode::RDN : RoundingMode::RUP))
1061+
? 0x7F
1062+
: 0;
1063+
}
1064+
Bits<8> roundBits = sig & 0x7f;
1065+
1066+
if ( 0xFD <= exp ) {
1067+
if ($signed(exp) < 's0) {
1068+
Boolean isTiny =
1069+
($signed(exp) < -8's1) || (sig + roundIncrement < 0x80000000);
1070+
sig = softfloat_shiftRightJam32( sig, -exp );
1071+
exp = 0;
1072+
roundBits = sig & 0x7F;
1073+
} else if ('shFD < $signed(exp) || (0x80000000 <= sig + roundIncrement)) {
1074+
return packToF32UI(sign, 0xFF, 0) - ((roundIncrement == 0) ? 1 : 0);
1075+
}
1076+
}
1077+
1078+
sig = (sig + roundIncrement) >> 7;
1079+
sig = sig & ~((roundBits ^ 0x40) & ((mode == RoundingMode::RNE) ? 1 : 0));
1080+
if ( sig == 0 ) {
1081+
exp = 0;
1082+
}
1083+
return packToF32UI(sign, exp, sig);
1084+
}
1085+
}
1086+
1087+
function softfloat_normRoundPackToF32_no_flag {
1088+
returns Bits<32>
1089+
arguments
1090+
Bits<1> sign,
1091+
Bits<8> exp,
1092+
Bits<23> sig,
1093+
RoundingMode mode
1094+
description {
1095+
Normalize, round, and pack into a 32-bit floating point value
1096+
No flags to be set
1097+
}
1098+
body {
1099+
Bits<8> shiftDist = count_leading_zeros<32>(sig) - 1;
1100+
exp = exp - shiftDist;
1101+
if ((7 <= shiftDist) && (exp < 0xFD)) {
1102+
return packToF32UI(sign, (sig != 0) ? exp : 0, sig << (shiftDist - 7));
1103+
} else {
1104+
return softfloat_roundPackToF32_no_flag(sign, exp, sig << shiftDist, mode);
1105+
}
1106+
}
1107+
}
1108+
1109+
function i32_to_f32_no_flag {
1110+
returns U32
1111+
arguments
1112+
U32 a,
1113+
RoundingMode mode
1114+
description {
1115+
Converts 32-bit signed integer to 32-bit floating point number
1116+
No flags to be set
1117+
}
1118+
body {
1119+
# sign of integer, it is 1 when negative
1120+
Bits<1> sign = a[31];
1121+
if ((a & 0x7FFFFFFF) == 0) {
1122+
return (sign == 1) ? packToF32UI(1, 0x9E, 0) : packToF32UI(0, 0, 0);
1123+
}
1124+
U32 magnitude_of_A = returnMag(a);
1125+
return softfloat_normRoundPackToF32_no_flag(sign, 0x9C, magnitude_of_A, mode);
1126+
}
1127+
}
1128+
1129+
function softfloat_roundToI32_no_flag {
1130+
returns Bits<32>
1131+
arguments
1132+
Bits<1> sign,
1133+
Bits<64> sig,
1134+
RoundingMode roundingMode
1135+
description {
1136+
Round to signed 32-bit integer, using +rounding_mode+
1137+
No flag to be set
1138+
}
1139+
body {
1140+
Bits<16> roundIncrement = 0x800;
1141+
if (
1142+
(roundingMode != RoundingMode::RMM)
1143+
&& (roundingMode != RoundingMode::RNE)
1144+
) {
1145+
roundIncrement = 0;
1146+
if (
1147+
sign == 1
1148+
? (roundingMode == RoundingMode::RDN)
1149+
: (roundingMode == RoundingMode::RUP)
1150+
) {
1151+
roundIncrement = 0xFFF;
1152+
}
1153+
}
1154+
Bits<16> roundBits = sig & 0xFFF;
1155+
sig = sig + roundIncrement;
1156+
if ((sig & 0xFFFFF00000000000) != 0) {
1157+
return sign == 1 ? WORD_NEG_OVERFLOW : WORD_POS_OVERFLOW;
1158+
}
1159+
1160+
Bits<32> sig32 = sig >> 12;
1161+
if (
1162+
(roundBits == 0x800 && (roundingMode == RoundingMode::RNE))
1163+
) {
1164+
sig32 = sig32 & ~32'b1;
1165+
}
1166+
1167+
Bits<32> z = (sign == 1) ? -sig32 : sig32;
1168+
if ((z != 0) && (($signed(z) < 's0) != (sign == 1))) {
1169+
return sign == 1 ? WORD_NEG_OVERFLOW : WORD_POS_OVERFLOW;
1170+
}
1171+
1172+
return z;
1173+
}
1174+
}
1175+
1176+
function f32_to_i32_no_flag {
1177+
returns U32
1178+
arguments
1179+
U32 a,
1180+
RoundingMode mode
1181+
description {
1182+
Converts 32-bit floating point number to a signed 32-bit integer
1183+
No flags to be set
1184+
}
1185+
body {
1186+
Bits<1> sign = signF32UI(a);
1187+
Bits<8> exp = expF32UI(a);
1188+
Bits<23> sig = fracF32UI(a);
1189+
Bits<8> shiftDist;
1190+
U64 sig64;
1191+
# for NaN return the highest positive value and set floating-point flag to invalid.
1192+
if ((exp == 8'hFF) && (sig != 0)) {
1193+
sign = 0;
1194+
return I32_NAN;
1195+
}
1196+
1197+
# MSB of significand is set to 1 because minimum 32-bit integer in IEEE 754 is 32'h80000000
1198+
if (exp != 0) {
1199+
sig = sig | 32'h00800000;
1200+
}
1201+
1202+
sig64 = sig `<< 32;
1203+
shiftDist = 8'hAA - exp;
1204+
1205+
if (shiftDist > 0) {
1206+
sig64 = softfloat_shiftRightJam64( sig64, shiftDist);
1207+
}
1208+
1209+
return softfloat_roundToI32_no_flag(sign, sig64, mode);
1210+
}
1211+
}
1212+
1213+
function round_f32_to_integral {
1214+
returns U32
1215+
arguments
1216+
U32 a,
1217+
RoundingMode mode
1218+
description {
1219+
Rounds 32-bit floating point number to a signed 32-bit integer.
1220+
This 32-bit integer is represented as a floating point number and returned.
1221+
}
1222+
body {
1223+
if ((is_sp_neg_inf?(a)) || (is_sp_pos_inf?(a)) || (is_sp_pos_zero?(a)) || (is_sp_neg_zero?(a))) {
1224+
# Return zero or infinity respectively for zero or infinity inputs
1225+
return a;
1226+
} else if (is_sp_signaling_nan?(a)) {
1227+
# set invalid flag for signaling NaN
1228+
set_fp_flag(FpFlag::NV);
1229+
return a;
1230+
}
1231+
# intermediate variable for storing 32-bit rounded integer
1232+
U32 intermediate;
1233+
# round 32-bit floating point number to integer, no flags to be set
1234+
intermediate = f32_to_i32_no_flag(a, mode);
1235+
# represent the integer as floating point number
1236+
return i32_to_f32_no_flag(intermediate, mode);
1237+
}
1238+
}

0 commit comments

Comments
 (0)