Skip to content

Commit f2d8e1b

Browse files
committed
Add Zfa extension support (excl. quad-precision)
This commit adds the following: - infrastructure for Zfa (e.g., existence macro) - support for the following instructions: + FLI.[HSD] + FMINM.[HSD] and FMAXM.[HSD] + FROUND.[HSD] and FROUNDNX.[HSD] + FMVH.X.D and FMVP.D.X + FLEQ.[HSD] and FLTQ.[HSD] + FCVTMOD.W.D Note the following implementation details: FMINM and FMAXM provide similar functionality to FMIN and FMAX, differing only in their NaN-handling: * FMIN/FMAX return a canonical NaN only if both operands are a NaN * FMINM/FMAXM return a canonical Nan if any operand is a NaN Consequently, the implementation is identical to FMIN/FMAX with only the NaN-related tests changed. FROUND instruction rounds a floating-point number in floating-point register rs1 and writes that integer, represented as a floating-point number to floating-point register rd while: * Zero and infinite inputs are copied to rd unmodified. * NaN inputs cause the invalid operation exception flag to be set. FROUNDNX instruction is defined similarly, but also sets the inexact exception flag if the input differs from the rounded result and is not NaN. FMVH.X.D instruction is available for RV32 only and moves bits 63:32 of floating-point register rs1 into integer register rd. FMVP.D.X instruction is available for RV32 only and moves a double-precision number from a pair of integer registers into a floating-point register. Integer registers rs1 and rs2 supply bits 31:0 and 63:32, respectively. FLEQ and FLTQ instructions are defined like the FLE and FLT instructions, except that quiet NaN inputs do not cause the invalid operation exception flag to be set. The FCVTMOD.W.D instruction is defined similarly to the FCVT.W.D instruction, with the following differences: * FCVTMOD.W.D always rounds towards zero. * Bits 31:0 are taken from the rounded, unbounded two's complement result, then sign-extended to XLEN bits and written to integer register rd. * Positive infinity, negative infinity and NaN are converted to zero. Signed-off-by: Charalampos Mitrodimas <[email protected]> Signed-off-by: Philipp Tomsich <[email protected]>
1 parent 3d9db22 commit f2d8e1b

File tree

9 files changed

+1067
-6
lines changed

9 files changed

+1067
-6
lines changed

Makefile

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,9 @@ SAIL_DEFAULT_INST += riscv_insts_zbc.sail
2929
SAIL_DEFAULT_INST += riscv_insts_zbs.sail
3030

3131
SAIL_DEFAULT_INST += riscv_insts_zfh.sail
32+
# Zfa needs to be added after fext, dext and Zfh (as it needs
33+
# definitions from those)
34+
SAIL_DEFAULT_INST += riscv_insts_zfa.sail
3235

3336
SAIL_DEFAULT_INST += riscv_insts_zkn.sail
3437
SAIL_DEFAULT_INST += riscv_insts_zks.sail

c_emulator/riscv_softfloat.c

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -641,6 +641,19 @@ unit softfloat_f16lt(mach_bits v1, mach_bits v2) {
641641
return UNIT;
642642
}
643643

644+
unit softfloat_f16lt_quiet(mach_bits v1, mach_bits v2) {
645+
SOFTFLOAT_PRELUDE(0);
646+
647+
float16_t a, b, res;
648+
a.v = v1;
649+
b.v = v2;
650+
res.v = f16_lt_quiet(a, b);
651+
652+
SOFTFLOAT_POSTLUDE(res);
653+
654+
return UNIT;
655+
}
656+
644657
unit softfloat_f16le(mach_bits v1, mach_bits v2) {
645658
SOFTFLOAT_PRELUDE(0);
646659

@@ -654,6 +667,19 @@ unit softfloat_f16le(mach_bits v1, mach_bits v2) {
654667
return UNIT;
655668
}
656669

670+
unit softfloat_f16le_quiet(mach_bits v1, mach_bits v2) {
671+
SOFTFLOAT_PRELUDE(0);
672+
673+
float16_t a, b, res;
674+
a.v = v1;
675+
b.v = v2;
676+
res.v = f16_le_quiet(a, b);
677+
678+
SOFTFLOAT_POSTLUDE(res);
679+
680+
return UNIT;
681+
}
682+
657683
unit softfloat_f16eq(mach_bits v1, mach_bits v2) {
658684
SOFTFLOAT_PRELUDE(0);
659685

@@ -680,6 +706,19 @@ unit softfloat_f32lt(mach_bits v1, mach_bits v2) {
680706
return UNIT;
681707
}
682708

709+
unit softfloat_f32lt_quiet(mach_bits v1, mach_bits v2) {
710+
SOFTFLOAT_PRELUDE(0);
711+
712+
float32_t a, b, res;
713+
a.v = v1;
714+
b.v = v2;
715+
res.v = f32_lt_quiet(a, b);
716+
717+
SOFTFLOAT_POSTLUDE(res);
718+
719+
return UNIT;
720+
}
721+
683722
unit softfloat_f32le(mach_bits v1, mach_bits v2) {
684723
SOFTFLOAT_PRELUDE(0);
685724

@@ -693,6 +732,20 @@ unit softfloat_f32le(mach_bits v1, mach_bits v2) {
693732
return UNIT;
694733
}
695734

735+
736+
unit softfloat_f32le_quiet(mach_bits v1, mach_bits v2) {
737+
SOFTFLOAT_PRELUDE(0);
738+
739+
float32_t a, b, res;
740+
a.v = v1;
741+
b.v = v2;
742+
res.v = f32_le_quiet(a, b);
743+
744+
SOFTFLOAT_POSTLUDE(res);
745+
746+
return UNIT;
747+
}
748+
696749
unit softfloat_f32eq(mach_bits v1, mach_bits v2) {
697750
SOFTFLOAT_PRELUDE(0);
698751

@@ -719,6 +772,19 @@ unit softfloat_f64lt(mach_bits v1, mach_bits v2) {
719772
return UNIT;
720773
}
721774

775+
unit softfloat_f64lt_quiet(mach_bits v1, mach_bits v2) {
776+
SOFTFLOAT_PRELUDE(0);
777+
778+
float64_t a, b, res;
779+
a.v = v1;
780+
b.v = v2;
781+
res.v = f64_lt_quiet(a, b);
782+
783+
SOFTFLOAT_POSTLUDE(res);
784+
785+
return UNIT;
786+
}
787+
722788
unit softfloat_f64le(mach_bits v1, mach_bits v2) {
723789
SOFTFLOAT_PRELUDE(0);
724790

@@ -732,6 +798,19 @@ unit softfloat_f64le(mach_bits v1, mach_bits v2) {
732798
return UNIT;
733799
}
734800

801+
unit softfloat_f64le_quiet(mach_bits v1, mach_bits v2) {
802+
SOFTFLOAT_PRELUDE(0);
803+
804+
float64_t a, b, res;
805+
a.v = v1;
806+
b.v = v2;
807+
res.v = f64_le_quiet(a, b);
808+
809+
SOFTFLOAT_POSTLUDE(res);
810+
811+
return UNIT;
812+
}
813+
735814
unit softfloat_f64eq(mach_bits v1, mach_bits v2) {
736815
SOFTFLOAT_PRELUDE(0);
737816

@@ -744,3 +823,42 @@ unit softfloat_f64eq(mach_bits v1, mach_bits v2) {
744823

745824
return UNIT;
746825
}
826+
827+
unit softfloat_f16roundToInt(mach_bits rm, mach_bits v, bool exact) {
828+
SOFTFLOAT_PRELUDE(rm);
829+
830+
float16_t a, res;
831+
uint_fast8_t rm8 = uint8_of_rm(rm);
832+
a.v = v;
833+
res = f16_roundToInt(a, rm8, exact);
834+
835+
SOFTFLOAT_POSTLUDE(res);
836+
837+
return UNIT;
838+
}
839+
840+
unit softfloat_f32roundToInt(mach_bits rm, mach_bits v, bool exact) {
841+
SOFTFLOAT_PRELUDE(rm);
842+
843+
float32_t a, res;
844+
uint_fast8_t rm8 = uint8_of_rm(rm);
845+
a.v = v;
846+
res = f32_roundToInt(a, rm8, exact);
847+
848+
SOFTFLOAT_POSTLUDE(res);
849+
850+
return UNIT;
851+
}
852+
853+
unit softfloat_f64roundToInt(mach_bits rm, mach_bits v, bool exact) {
854+
SOFTFLOAT_PRELUDE(rm);
855+
856+
float64_t a, res;
857+
uint_fast8_t rm8 = uint8_of_rm(rm);
858+
a.v = v;
859+
res = f64_roundToInt(a, rm8, exact);
860+
861+
SOFTFLOAT_POSTLUDE(res);
862+
863+
return UNIT;
864+
}

c_emulator/riscv_softfloat.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,11 +62,21 @@ unit softfloat_f64tof16(mach_bits rm, mach_bits v);
6262
unit softfloat_f64tof32(mach_bits rm, mach_bits v);
6363

6464
unit softfloat_f16lt(mach_bits v1, mach_bits v2);
65+
unit softfloat_f16lt_quiet(mach_bits v1, mach_bits v2);
6566
unit softfloat_f16le(mach_bits v1, mach_bits v2);
67+
unit softfloat_f16le_quiet(mach_bits v1, mach_bits v2);
6668
unit softfloat_f16eq(mach_bits v1, mach_bits v2);
6769
unit softfloat_f32lt(mach_bits v1, mach_bits v2);
70+
unit softfloat_f32lt_quiet(mach_bits v1, mach_bits v2);
6871
unit softfloat_f32le(mach_bits v1, mach_bits v2);
72+
unit softfloat_f32le_quiet(mach_bits v1, mach_bits v2);
6973
unit softfloat_f32eq(mach_bits v1, mach_bits v2);
7074
unit softfloat_f64lt(mach_bits v1, mach_bits v2);
75+
unit softfloat_f64lt_quiet(mach_bits v1, mach_bits v2);
7176
unit softfloat_f64le(mach_bits v1, mach_bits v2);
77+
unit softfloat_f64le_quiet(mach_bits v1, mach_bits v2);
7278
unit softfloat_f64eq(mach_bits v1, mach_bits v2);
79+
80+
unit softfloat_f16roundToInt(mach_bits rm, mach_bits v, bool exact);
81+
unit softfloat_f32roundToInt(mach_bits rm, mach_bits v, bool exact);
82+
unit softfloat_f64roundToInt(mach_bits rm, mach_bits v, bool exact);

handwritten_support/0.11/riscv_extras_fdext.lem

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,26 +164,53 @@ let softfloat_f64_to_f32 _ _ = ()
164164
val softfloat_f16_lt : forall 's. Size 's => bitvector 's -> bitvector 's -> unit
165165
let softfloat_f16_lt _ _ = ()
166166

167+
val softfloat_f16_lt_quiet : forall 's. Size 's => bitvector 's -> bitvector 's -> unit
168+
let softfloat_f16_lt_quiet _ _ = ()
169+
167170
val softfloat_f16_le : forall 's. Size 's => bitvector 's -> bitvector 's -> unit
168171
let softfloat_f16_le _ _ = ()
169172

173+
val softfloat_f16_le_quiet : forall 's. Size 's => bitvector 's -> bitvector 's -> unit
174+
let softfloat_f16_le_quiet _ _ = ()
175+
170176
val softfloat_f16_eq : forall 's. Size 's => bitvector 's -> bitvector 's -> unit
171177
let softfloat_f16_eq _ _ = ()
172178

173179
val softfloat_f32_lt : forall 's. Size 's => bitvector 's -> bitvector 's -> unit
174180
let softfloat_f32_lt _ _ = ()
175181

182+
val softfloat_f32_lt_quiet : forall 's. Size 's => bitvector 's -> bitvector 's -> unit
183+
let softfloat_f32_lt_quiet _ _ = ()
184+
176185
val softfloat_f32_le : forall 's. Size 's => bitvector 's -> bitvector 's -> unit
177186
let softfloat_f32_le _ _ = ()
178187

188+
val softfloat_f32_le_quiet : forall 's. Size 's => bitvector 's -> bitvector 's -> unit
189+
let softfloat_f32_le_quiet _ _ = ()
190+
179191
val softfloat_f32_eq : forall 's. Size 's => bitvector 's -> bitvector 's -> unit
180192
let softfloat_f32_eq _ _ = ()
181193

182194
val softfloat_f64_lt : forall 's. Size 's => bitvector 's -> bitvector 's -> unit
183195
let softfloat_f64_lt _ _ = ()
184196

197+
val softfloat_f64_lt_quiet : forall 's. Size 's => bitvector 's -> bitvector 's -> unit
198+
let softfloat_f64_lt_quiet _ _ = ()
199+
185200
val softfloat_f64_le : forall 's. Size 's => bitvector 's -> bitvector 's -> unit
186201
let softfloat_f64_le _ _ = ()
187202

203+
val softfloat_f64_le_quiet : forall 's. Size 's => bitvector 's -> bitvector 's -> unit
204+
let softfloat_f64_le_quiet _ _ = ()
205+
188206
val softfloat_f64_eq : forall 's. Size 's => bitvector 's -> bitvector 's -> unit
189207
let softfloat_f64_eq _ _ = ()
208+
209+
val softfloat_f16_round_to_int : forall 'rm 's. Size 'rm, Size 's => bitvector 'rm -> bitvector 's -> bool -> unit
210+
let softfloat_f16_round_to_int _ _ _ = ()
211+
212+
val softfloat_f32_round_to_int : forall 'rm 's. Size 'rm, Size 's => bitvector 'rm -> bitvector 's -> bool -> unit
213+
let softfloat_f32_round_to_int _ _ _ = ()
214+
215+
val softfloat_f64_round_to_int : forall 'rm 's. Size 'rm, Size 's => bitvector 'rm -> bitvector 's -> bool -> unit
216+
let softfloat_f64_round_to_int _ _ _ = ()

model/riscv_fdext_regs.sail

Lines changed: 52 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -270,12 +270,58 @@ function wF_bits(i: bits(5), data: flenbits) -> unit = {
270270

271271
overload F = {rF_bits, wF_bits, rF, wF}
272272

273+
val rF_H : bits(5) -> bits(16) effect {escape, rreg}
274+
function rF_H(i) = {
275+
assert(sizeof(flen) >= 16);
276+
assert(sys_enable_fdext() & not(sys_enable_zfinx()));
277+
nan_unbox(F(i))
278+
}
279+
280+
val wF_H : (bits(5), bits(16)) -> unit effect {escape, wreg}
281+
function wF_H(i, data) = {
282+
assert(sizeof(flen) >= 16);
283+
assert(sys_enable_fdext() & not(sys_enable_zfinx()));
284+
F(i) = nan_box(data)
285+
}
286+
287+
val rF_S : bits(5) -> bits(32) effect {escape, rreg}
288+
function rF_S(i) = {
289+
assert(sizeof(flen) >= 32);
290+
assert(sys_enable_fdext() & not(sys_enable_zfinx()));
291+
nan_unbox(F(i))
292+
}
293+
294+
val wF_S : (bits(5), bits(32)) -> unit effect {escape, wreg}
295+
function wF_S(i, data) = {
296+
assert(sizeof(flen) >= 32);
297+
assert(sys_enable_fdext() & not(sys_enable_zfinx()));
298+
F(i) = nan_box(data)
299+
}
300+
301+
val rF_D : bits(5) -> bits(64) effect {escape, rreg}
302+
function rF_D(i) = {
303+
assert(sizeof(flen) >= 64);
304+
assert(sys_enable_fdext() & not(sys_enable_zfinx()));
305+
F(i)
306+
}
307+
308+
val wF_D : (bits(5), bits(64)) -> unit effect {escape, wreg}
309+
function wF_D(i, data) = {
310+
assert(sizeof(flen) >= 64);
311+
assert(sys_enable_fdext() & not(sys_enable_zfinx()));
312+
F(i) = data
313+
}
314+
315+
overload F_H = { rF_H, wF_H }
316+
overload F_S = { rF_S, wF_S }
317+
overload F_D = { rF_D, wF_D }
318+
273319
val rF_or_X_H : bits(5) -> bits(16) effect {escape, rreg}
274320
function rF_or_X_H(i) = {
275321
assert(sizeof(flen) >= 16);
276322
assert(sys_enable_fdext() != sys_enable_zfinx());
277323
if sys_enable_fdext()
278-
then nan_unbox(F(i))
324+
then F_H(i)
279325
else X(i)[15..0]
280326
}
281327

@@ -284,7 +330,7 @@ function rF_or_X_S(i) = {
284330
assert(sizeof(flen) >= 32);
285331
assert(sys_enable_fdext() != sys_enable_zfinx());
286332
if sys_enable_fdext()
287-
then nan_unbox(F(i))
333+
then F_S(i)
288334
else X(i)[31..0]
289335
}
290336

@@ -293,7 +339,7 @@ function rF_or_X_D(i) = {
293339
assert(sizeof(flen) >= 64);
294340
assert(sys_enable_fdext() != sys_enable_zfinx());
295341
if sys_enable_fdext()
296-
then F(unsigned(i))
342+
then F_D(i)
297343
else if sizeof(xlen) >= 64
298344
then X(i)[63..0]
299345
else {
@@ -307,7 +353,7 @@ function wF_or_X_H(i, data) = {
307353
assert(sizeof(flen) >= 16);
308354
assert(sys_enable_fdext() != sys_enable_zfinx());
309355
if sys_enable_fdext()
310-
then F(i) = nan_box(data)
356+
then F_H(i) = data
311357
else X(i) = EXTS(data)
312358
}
313359

@@ -316,7 +362,7 @@ function wF_or_X_S(i, data) = {
316362
assert(sizeof(flen) >= 32);
317363
assert(sys_enable_fdext() != sys_enable_zfinx());
318364
if sys_enable_fdext()
319-
then F(i) = nan_box(data)
365+
then F_S(i) = data
320366
else X(i) = EXTS(data)
321367
}
322368

@@ -325,7 +371,7 @@ function wF_or_X_D(i, data) = {
325371
assert (sizeof(flen) >= 64);
326372
assert(sys_enable_fdext() != sys_enable_zfinx());
327373
if sys_enable_fdext()
328-
then F(i) = data
374+
then F_D(i) = data
329375
else if sizeof(xlen) >= 64
330376
then X(i) = EXTS(data)
331377
else {

0 commit comments

Comments
 (0)