Skip to content

Commit

Permalink
Simplify softfloat interface
Browse files Browse the repository at this point in the history
Currently the softfloat interface relies on two global registers defined in Sail to return values, one of which is a mirror of `fflags`. Unfortunately this doesn't work if the model is compiled with `-static` or wrapped in an anonymous namespace (I am doing the latter in a similar way to [@arichardson's method here](https://github.com/CTSRD-CHERI/cheri-compressed-cap/blob/89d21384c0183e5c422e23e1e5b37e127ad14e96/test/sail_wrapper_common.c#L50)).

This commit changes the design so that there is only a one-way dependency - the softfloat implementation does not depend on the model. This is done by returning the result of the floating point operation as a normal function return value, and then the model retrieves the new flags by simply calling another platform function (`extern_float_flags()`).

This is a bit cleaner, works with `-static` and also removes the need for `write_fflags()` and `update_softfloat_fflags()`.

Tested with `run_fp_tests.sh` - all 82 tests pass.
  • Loading branch information
Timmmm committed Aug 4, 2023
1 parent 58cac61 commit 1093071
Show file tree
Hide file tree
Showing 8 changed files with 484 additions and 627 deletions.
403 changes: 136 additions & 267 deletions c_emulator/riscv_softfloat.c

Large diffs are not rendered by default.

160 changes: 81 additions & 79 deletions c_emulator/riscv_softfloat.h
Original file line number Diff line number Diff line change
@@ -1,85 +1,87 @@
#pragma once

unit softfloat_f16add(mach_bits rm, mach_bits v1, mach_bits v2);
unit softfloat_f16sub(mach_bits rm, mach_bits v1, mach_bits v2);
unit softfloat_f16mul(mach_bits rm, mach_bits v1, mach_bits v2);
unit softfloat_f16div(mach_bits rm, mach_bits v1, mach_bits v2);

unit softfloat_f32add(mach_bits rm, mach_bits v1, mach_bits v2);
unit softfloat_f32sub(mach_bits rm, mach_bits v1, mach_bits v2);
unit softfloat_f32mul(mach_bits rm, mach_bits v1, mach_bits v2);
unit softfloat_f32div(mach_bits rm, mach_bits v1, mach_bits v2);

unit softfloat_f64add(mach_bits rm, mach_bits v1, mach_bits v2);
unit softfloat_f64sub(mach_bits rm, mach_bits v1, mach_bits v2);
unit softfloat_f64mul(mach_bits rm, mach_bits v1, mach_bits v2);
unit softfloat_f64div(mach_bits rm, mach_bits v1, mach_bits v2);

unit softfloat_f16muladd(mach_bits rm, mach_bits v1, mach_bits v2,
mach_bits softfloat_float_flags(unit);

mach_bits softfloat_f16add(mach_bits rm, mach_bits v1, mach_bits v2);
mach_bits softfloat_f16sub(mach_bits rm, mach_bits v1, mach_bits v2);
mach_bits softfloat_f16mul(mach_bits rm, mach_bits v1, mach_bits v2);
mach_bits softfloat_f16div(mach_bits rm, mach_bits v1, mach_bits v2);

mach_bits softfloat_f32add(mach_bits rm, mach_bits v1, mach_bits v2);
mach_bits softfloat_f32sub(mach_bits rm, mach_bits v1, mach_bits v2);
mach_bits softfloat_f32mul(mach_bits rm, mach_bits v1, mach_bits v2);
mach_bits softfloat_f32div(mach_bits rm, mach_bits v1, mach_bits v2);

mach_bits softfloat_f64add(mach_bits rm, mach_bits v1, mach_bits v2);
mach_bits softfloat_f64sub(mach_bits rm, mach_bits v1, mach_bits v2);
mach_bits softfloat_f64mul(mach_bits rm, mach_bits v1, mach_bits v2);
mach_bits softfloat_f64div(mach_bits rm, mach_bits v1, mach_bits v2);

mach_bits softfloat_f16muladd(mach_bits rm, mach_bits v1, mach_bits v2,
mach_bits v3);
unit softfloat_f32muladd(mach_bits rm, mach_bits v1, mach_bits v2,
mach_bits softfloat_f32muladd(mach_bits rm, mach_bits v1, mach_bits v2,
mach_bits v3);
unit softfloat_f64muladd(mach_bits rm, mach_bits v1, mach_bits v2,
mach_bits softfloat_f64muladd(mach_bits rm, mach_bits v1, mach_bits v2,
mach_bits v3);

unit softfloat_f16sqrt(mach_bits rm, mach_bits v);
unit softfloat_f32sqrt(mach_bits rm, mach_bits v);
unit softfloat_f64sqrt(mach_bits rm, mach_bits v);

unit softfloat_f16toi32(mach_bits rm, mach_bits v);
unit softfloat_f16toui32(mach_bits rm, mach_bits v);
unit softfloat_f16toi64(mach_bits rm, mach_bits v);
unit softfloat_f16toui64(mach_bits rm, mach_bits v);

unit softfloat_f32toi32(mach_bits rm, mach_bits v);
unit softfloat_f32toui32(mach_bits rm, mach_bits v);
unit softfloat_f32toi64(mach_bits rm, mach_bits v);
unit softfloat_f32toui64(mach_bits rm, mach_bits v);

unit softfloat_f64toi32(mach_bits rm, mach_bits v);
unit softfloat_f64toui32(mach_bits rm, mach_bits v);
unit softfloat_f64toi64(mach_bits rm, mach_bits v);
unit softfloat_f64toui64(mach_bits rm, mach_bits v);

unit softfloat_i32tof16(mach_bits rm, mach_bits v);
unit softfloat_ui32tof16(mach_bits rm, mach_bits v);
unit softfloat_i64tof16(mach_bits rm, mach_bits v);
unit softfloat_ui64tof16(mach_bits rm, mach_bits v);

unit softfloat_i32tof32(mach_bits rm, mach_bits v);
unit softfloat_ui32tof32(mach_bits rm, mach_bits v);
unit softfloat_i64tof32(mach_bits rm, mach_bits v);
unit softfloat_ui64tof32(mach_bits rm, mach_bits v);

unit softfloat_i32tof64(mach_bits rm, mach_bits v);
unit softfloat_ui32tof64(mach_bits rm, mach_bits v);
unit softfloat_i64tof64(mach_bits rm, mach_bits v);
unit softfloat_ui64tof64(mach_bits rm, mach_bits v);

unit softfloat_f16tof32(mach_bits rm, mach_bits v);
unit softfloat_f16tof64(mach_bits rm, mach_bits v);
unit softfloat_f32tof64(mach_bits rm, mach_bits v);

unit softfloat_f32tof16(mach_bits rm, mach_bits v);
unit softfloat_f64tof16(mach_bits rm, mach_bits v);
unit softfloat_f64tof32(mach_bits rm, mach_bits v);

unit softfloat_f16lt(mach_bits v1, mach_bits v2);
unit softfloat_f16lt_quiet(mach_bits v1, mach_bits v2);
unit softfloat_f16le(mach_bits v1, mach_bits v2);
unit softfloat_f16le_quiet(mach_bits v1, mach_bits v2);
unit softfloat_f16eq(mach_bits v1, mach_bits v2);
unit softfloat_f32lt(mach_bits v1, mach_bits v2);
unit softfloat_f32lt_quiet(mach_bits v1, mach_bits v2);
unit softfloat_f32le(mach_bits v1, mach_bits v2);
unit softfloat_f32le_quiet(mach_bits v1, mach_bits v2);
unit softfloat_f32eq(mach_bits v1, mach_bits v2);
unit softfloat_f64lt(mach_bits v1, mach_bits v2);
unit softfloat_f64lt_quiet(mach_bits v1, mach_bits v2);
unit softfloat_f64le(mach_bits v1, mach_bits v2);
unit softfloat_f64le_quiet(mach_bits v1, mach_bits v2);
unit softfloat_f64eq(mach_bits v1, mach_bits v2);

unit softfloat_f16roundToInt(mach_bits rm, mach_bits v, bool exact);
unit softfloat_f32roundToInt(mach_bits rm, mach_bits v, bool exact);
unit softfloat_f64roundToInt(mach_bits rm, mach_bits v, bool exact);
mach_bits softfloat_f16sqrt(mach_bits rm, mach_bits v);
mach_bits softfloat_f32sqrt(mach_bits rm, mach_bits v);
mach_bits softfloat_f64sqrt(mach_bits rm, mach_bits v);

mach_bits softfloat_f16toi32(mach_bits rm, mach_bits v);
mach_bits softfloat_f16toui32(mach_bits rm, mach_bits v);
mach_bits softfloat_f16toi64(mach_bits rm, mach_bits v);
mach_bits softfloat_f16toui64(mach_bits rm, mach_bits v);

mach_bits softfloat_f32toi32(mach_bits rm, mach_bits v);
mach_bits softfloat_f32toui32(mach_bits rm, mach_bits v);
mach_bits softfloat_f32toi64(mach_bits rm, mach_bits v);
mach_bits softfloat_f32toui64(mach_bits rm, mach_bits v);

mach_bits softfloat_f64toi32(mach_bits rm, mach_bits v);
mach_bits softfloat_f64toui32(mach_bits rm, mach_bits v);
mach_bits softfloat_f64toi64(mach_bits rm, mach_bits v);
mach_bits softfloat_f64toui64(mach_bits rm, mach_bits v);

mach_bits softfloat_i32tof16(mach_bits rm, mach_bits v);
mach_bits softfloat_ui32tof16(mach_bits rm, mach_bits v);
mach_bits softfloat_i64tof16(mach_bits rm, mach_bits v);
mach_bits softfloat_ui64tof16(mach_bits rm, mach_bits v);

mach_bits softfloat_i32tof32(mach_bits rm, mach_bits v);
mach_bits softfloat_ui32tof32(mach_bits rm, mach_bits v);
mach_bits softfloat_i64tof32(mach_bits rm, mach_bits v);
mach_bits softfloat_ui64tof32(mach_bits rm, mach_bits v);

mach_bits softfloat_i32tof64(mach_bits rm, mach_bits v);
mach_bits softfloat_ui32tof64(mach_bits rm, mach_bits v);
mach_bits softfloat_i64tof64(mach_bits rm, mach_bits v);
mach_bits softfloat_ui64tof64(mach_bits rm, mach_bits v);

mach_bits softfloat_f16tof32(mach_bits rm, mach_bits v);
mach_bits softfloat_f16tof64(mach_bits rm, mach_bits v);
mach_bits softfloat_f32tof64(mach_bits rm, mach_bits v);

mach_bits softfloat_f32tof16(mach_bits rm, mach_bits v);
mach_bits softfloat_f64tof16(mach_bits rm, mach_bits v);
mach_bits softfloat_f64tof32(mach_bits rm, mach_bits v);

bool softfloat_f16lt(mach_bits v1, mach_bits v2);
bool softfloat_f16lt_quiet(mach_bits v1, mach_bits v2);
bool softfloat_f16le(mach_bits v1, mach_bits v2);
bool softfloat_f16le_quiet(mach_bits v1, mach_bits v2);
bool softfloat_f16eq(mach_bits v1, mach_bits v2);
bool softfloat_f32lt(mach_bits v1, mach_bits v2);
bool softfloat_f32lt_quiet(mach_bits v1, mach_bits v2);
bool softfloat_f32le(mach_bits v1, mach_bits v2);
bool softfloat_f32le_quiet(mach_bits v1, mach_bits v2);
bool softfloat_f32eq(mach_bits v1, mach_bits v2);
bool softfloat_f64lt(mach_bits v1, mach_bits v2);
bool softfloat_f64lt_quiet(mach_bits v1, mach_bits v2);
bool softfloat_f64le(mach_bits v1, mach_bits v2);
bool softfloat_f64le_quiet(mach_bits v1, mach_bits v2);
bool softfloat_f64eq(mach_bits v1, mach_bits v2);

mach_bits softfloat_f16roundToInt(mach_bits rm, mach_bits v, bool exact);
mach_bits softfloat_f32roundToInt(mach_bits rm, mach_bits v, bool exact);
mach_bits softfloat_f64roundToInt(mach_bits rm, mach_bits v, bool exact);
12 changes: 1 addition & 11 deletions model/riscv_fdext_regs.sail
Original file line number Diff line number Diff line change
Expand Up @@ -528,26 +528,16 @@ val ext_write_fcsr : (bits(3), bits(5)) -> unit effect {rreg, wreg, escape}
function ext_write_fcsr (frm, fflags) = {
fcsr->FRM() = frm; /* Note: frm can be an illegal value, 101, 110, 111 */
fcsr->FFLAGS() = fflags;
update_softfloat_fflags(fflags);
dirty_fd_context_if_present();
}

/* called for softfloat paths (softfloat flags are consistent) */
val write_fflags : (bits(5)) -> unit effect {rreg, wreg, escape}
function write_fflags(fflags) = {
if fcsr.FFLAGS() != fflags
then dirty_fd_context_if_present();
fcsr->FFLAGS() = fflags;
}

/* called for non-softfloat paths (softfloat flags need updating) */
/* OR flags into the fflags register. */
val accrue_fflags : (bits(5)) -> unit effect {rreg, wreg, escape}
function accrue_fflags(flags) = {
let f = fcsr.FFLAGS() | flags;
if fcsr.FFLAGS() != f
then {
fcsr->FFLAGS() = f;
update_softfloat_fflags(f);
dirty_fd_context_if_present();
}
}
32 changes: 16 additions & 16 deletions model/riscv_insts_dext.sail
Original file line number Diff line number Diff line change
Expand Up @@ -349,7 +349,7 @@ function clause execute (F_MADD_TYPE_D(rs3, rs2, rs1, rm, rd, op)) = {
FNMSUB_D => riscv_f64MulAdd (rm_3b, negate_D (rs1_val_64b), rs2_val_64b, rs3_val_64b),
FNMADD_D => riscv_f64MulAdd (rm_3b, negate_D (rs1_val_64b), rs2_val_64b, negate_D (rs3_val_64b))
};
write_fflags(fflags);
accrue_fflags(fflags);
F_or_X_D(rd) = rd_val_64b;
RETIRE_SUCCESS
}
Expand Down Expand Up @@ -413,7 +413,7 @@ function clause execute (F_BIN_RM_TYPE_D(rs2, rs1, rm, rd, op)) = {
FMUL_D => riscv_f64Mul (rm_3b, rs1_val_64b, rs2_val_64b),
FDIV_D => riscv_f64Div (rm_3b, rs1_val_64b, rs2_val_64b)
};
write_fflags(fflags);
accrue_fflags(fflags);
F_or_X_D(rd) = rd_val_64b;
RETIRE_SUCCESS
}
Expand Down Expand Up @@ -501,7 +501,7 @@ function clause execute (F_UN_RM_TYPE_D(rs1, rm, rd, FSQRT_D)) = {
let rm_3b = encdec_rounding_mode(rm');
let (fflags, rd_val_D) = riscv_f64Sqrt (rm_3b, rs1_val_D);

write_fflags(fflags);
accrue_fflags(fflags);
F_or_X_D(rd) = rd_val_D;
RETIRE_SUCCESS
}
Expand All @@ -516,7 +516,7 @@ function clause execute (F_UN_RM_TYPE_D(rs1, rm, rd, FCVT_W_D)) = {
let rm_3b = encdec_rounding_mode(rm');
let (fflags, rd_val_W) = riscv_f64ToI32 (rm_3b, rs1_val_D);

write_fflags(fflags);
accrue_fflags(fflags);
X(rd) = sign_extend (rd_val_W);
RETIRE_SUCCESS
}
Expand All @@ -531,7 +531,7 @@ function clause execute (F_UN_RM_TYPE_D(rs1, rm, rd, FCVT_WU_D)) = {
let rm_3b = encdec_rounding_mode(rm');
let (fflags, rd_val_WU) = riscv_f64ToUi32 (rm_3b, rs1_val_D);

write_fflags(fflags);
accrue_fflags(fflags);
X(rd) = sign_extend (rd_val_WU);
RETIRE_SUCCESS
}
Expand All @@ -546,7 +546,7 @@ function clause execute (F_UN_RM_TYPE_D(rs1, rm, rd, FCVT_D_W)) = {
let rm_3b = encdec_rounding_mode(rm');
let (fflags, rd_val_D) = riscv_i32ToF64 (rm_3b, rs1_val_W);

write_fflags(fflags);
accrue_fflags(fflags);
F_or_X_D(rd) = rd_val_D;
RETIRE_SUCCESS
}
Expand All @@ -561,7 +561,7 @@ function clause execute (F_UN_RM_TYPE_D(rs1, rm, rd, FCVT_D_WU)) = {
let rm_3b = encdec_rounding_mode(rm');
let (fflags, rd_val_D) = riscv_ui32ToF64 (rm_3b, rs1_val_WU);

write_fflags(fflags);
accrue_fflags(fflags);
F_or_X_D(rd) = rd_val_D;
RETIRE_SUCCESS
}
Expand All @@ -576,7 +576,7 @@ function clause execute (F_UN_RM_TYPE_D(rs1, rm, rd, FCVT_S_D)) = {
let rm_3b = encdec_rounding_mode(rm');
let (fflags, rd_val_S) = riscv_f64ToF32 (rm_3b, rs1_val_D);

write_fflags(fflags);
accrue_fflags(fflags);
F_or_X_S(rd) = rd_val_S;
RETIRE_SUCCESS
}
Expand All @@ -591,7 +591,7 @@ function clause execute (F_UN_RM_TYPE_D(rs1, rm, rd, FCVT_D_S)) = {
let rm_3b = encdec_rounding_mode(rm');
let (fflags, rd_val_D) = riscv_f32ToF64 (rm_3b, rs1_val_S);

write_fflags(fflags);
accrue_fflags(fflags);
F_or_X_D(rd) = rd_val_D;
RETIRE_SUCCESS
}
Expand All @@ -607,7 +607,7 @@ function clause execute (F_UN_RM_TYPE_D(rs1, rm, rd, FCVT_L_D)) = {
let rm_3b = encdec_rounding_mode(rm');
let (fflags, rd_val_L) = riscv_f64ToI64 (rm_3b, rs1_val_D);

write_fflags(fflags);
accrue_fflags(fflags);
X(rd) = sign_extend(rd_val_L);
RETIRE_SUCCESS
}
Expand All @@ -623,7 +623,7 @@ function clause execute (F_UN_RM_TYPE_D(rs1, rm, rd, FCVT_LU_D)) = {
let rm_3b = encdec_rounding_mode(rm');
let (fflags, rd_val_LU) = riscv_f64ToUi64 (rm_3b, rs1_val_D);

write_fflags(fflags);
accrue_fflags(fflags);
X(rd) = sign_extend(rd_val_LU);
RETIRE_SUCCESS
}
Expand All @@ -639,7 +639,7 @@ function clause execute (F_UN_RM_TYPE_D(rs1, rm, rd, FCVT_D_L)) = {
let rm_3b = encdec_rounding_mode(rm');
let (fflags, rd_val_D) = riscv_i64ToF64 (rm_3b, rs1_val_L);

write_fflags(fflags);
accrue_fflags(fflags);
F_or_X_D(rd) = rd_val_D;
RETIRE_SUCCESS
}
Expand All @@ -655,7 +655,7 @@ function clause execute (F_UN_RM_TYPE_D(rs1, rm, rd, FCVT_D_LU)) = {
let rm_3b = encdec_rounding_mode(rm');
let (fflags, rd_val_D) = riscv_ui64ToF64 (rm_3b, rs1_val_LU);

write_fflags(fflags);
accrue_fflags(fflags);
F_or_X_D(rd) = rd_val_D;
RETIRE_SUCCESS
}
Expand Down Expand Up @@ -862,7 +862,7 @@ function clause execute (F_BIN_TYPE_D(rs2, rs1, rd, FEQ_D)) = {
let (fflags, rd_val) : (bits_fflags, bool) =
riscv_f64Eq (rs1_val_D, rs2_val_D);

write_fflags(fflags);
accrue_fflags(fflags);
X(rd) = zero_extend(bool_to_bits(rd_val));
RETIRE_SUCCESS
}
Expand All @@ -874,7 +874,7 @@ function clause execute (F_BIN_TYPE_D(rs2, rs1, rd, FLT_D)) = {
let (fflags, rd_val) : (bits_fflags, bool) =
riscv_f64Lt (rs1_val_D, rs2_val_D);

write_fflags(fflags);
accrue_fflags(fflags);
X(rd) = zero_extend(bool_to_bits(rd_val));
RETIRE_SUCCESS
}
Expand All @@ -886,7 +886,7 @@ function clause execute (F_BIN_TYPE_D(rs2, rs1, rd, FLE_D)) = {
let (fflags, rd_val) : (bits_fflags, bool) =
riscv_f64Le (rs1_val_D, rs2_val_D);

write_fflags(fflags);
accrue_fflags(fflags);
X(rd) = zero_extend(bool_to_bits(rd_val));
RETIRE_SUCCESS
}
Expand Down
Loading

0 comments on commit 1093071

Please sign in to comment.