This commit provides the basic operation support for the OCP float4 data
type(e2m1).
Signed-off-by: Max Chou <max.chou@sifive.com>
---
fpu/softfloat.c | 29 +++++++++++++++++++++++
include/fpu/softfloat-types.h | 5 ++++
include/fpu/softfloat.h | 43 +++++++++++++++++++++++++++++++++++
3 files changed, 77 insertions(+)
diff --git a/fpu/softfloat.c b/fpu/softfloat.c
index 533f96dcda..96845e86df 100644
--- a/fpu/softfloat.c
+++ b/fpu/softfloat.c
@@ -595,6 +595,13 @@ static inline bool fmt_has_nan_encoding(const FloatFmt *fmt)
.frac_shift = (-F - 1) & 63, \
.round_mask = (1ull << ((-F - 1) & 63)) - 1
+static const FloatFmt float4_e2m1_params = {
+ FLOAT_PARAMS(2, 1),
+ .no_infinity = true,
+ .limited_nan = true,
+ .normal_frac_max = NORMAL_FRAC_MAX_ALL,
+};
+
static const FloatFmt float8_e4m3_params = {
FLOAT_PARAMS(4, 3),
.no_infinity = true,
@@ -663,6 +670,11 @@ static void unpack_raw64(FloatParts64 *r, const FloatFmt *fmt, uint64_t raw)
};
}
+static void QEMU_FLATTEN float4_e2m1_unpack_raw(FloatParts64 *p, float4_e2m1 f)
+{
+ unpack_raw64(p, &float4_e2m1_params, f);
+}
+
static void QEMU_FLATTEN float8_e4m3_unpack_raw(FloatParts64 *p, float8_e4m3 f)
{
unpack_raw64(p, &float8_e4m3_params, f);
@@ -1745,6 +1757,13 @@ static const uint16_t rsqrt_tab[128] = {
* Pack/unpack routines with a specific FloatFmt.
*/
+static void float4_e2m1_unpack_canonical(FloatParts64 *p, float4_e2m1 f,
+ float_status *s)
+{
+ float4_e2m1_unpack_raw(p, f);
+ parts_canonicalize(p, s, &float4_e2m1_params);
+}
+
static void float8_e4m3_unpack_canonical(FloatParts64 *p, float8_e4m3 f,
float_status *s)
{
@@ -2938,6 +2957,16 @@ static void parts_float_to_float_widen(FloatParts128 *a, FloatParts64 *b,
}
}
+float8_e4m3 float4_e2m1_to_float8_e4m3(float4_e2m1 a, float_status *s)
+{
+ FloatParts64 p;
+
+ float4_e2m1_unpack_canonical(&p, a, s);
+ parts_float_to_float(&p, s);
+
+ return float8_e4m3_round_pack_canonical(&p, s, &float8_e4m3_params, false);
+}
+
bfloat16 float8_e4m3_to_bfloat16(float8_e4m3 a, float_status *s)
{
FloatParts64 p;
diff --git a/include/fpu/softfloat-types.h b/include/fpu/softfloat-types.h
index b781bf10b7..f8cadffff4 100644
--- a/include/fpu/softfloat-types.h
+++ b/include/fpu/softfloat-types.h
@@ -131,6 +131,11 @@ typedef uint8_t float8_e5m2;
#define const_float8_e4m3(x) (x)
#define const_float8_e5m2(x) (x)
+typedef uint8_t float4_e2m1;
+#define float4_e2m1_val(x) ((x) & 0xf)
+#define make_float4_e2m1(x) ((x) & 0xf)
+#define const_float4_e2m1(x) ((x) & 0xf)
+
/*
* Software IEC/IEEE floating-point underflow tininess-detection mode.
*/
diff --git a/include/fpu/softfloat.h b/include/fpu/softfloat.h
index 7abbf92b7e..888efed288 100644
--- a/include/fpu/softfloat.h
+++ b/include/fpu/softfloat.h
@@ -200,6 +200,8 @@ float8_e5m2 bfloat16_to_float8_e5m2(bfloat16, bool saturate, float_status *statu
float8_e4m3 float32_to_float8_e4m3(float32, bool saturate, float_status *status);
float8_e5m2 float32_to_float8_e5m2(float32, bool saturate, float_status *status);
+float8_e4m3 float4_e2m1_to_float8_e4m3(float4_e2m1, float_status *status);
+
/*----------------------------------------------------------------------------
| Software OCP operations.
*----------------------------------------------------------------------------*/
@@ -270,6 +272,47 @@ static inline bool float8_e5m2_is_normal(float8_e5m2 a)
return (((float8_e5m2_val(a) >> 2) + 1) & 0x1f) >= 2;
}
+static inline bool float4_e2m1_is_quiet_nan(float4_e2m1 a, float_status *status)
+{
+ return false;
+}
+
+static inline bool float4_e2m1_is_signaling_nan(float4_e2m1 a, float_status *status)
+{
+ return false;
+}
+
+static inline bool float4_e2m1_is_any_nan(float4_e2m1 a)
+{
+ return false;
+}
+
+static inline bool float4_e2m1_is_neg(float4_e2m1 a)
+{
+ return float4_e2m1_val(a) >> 3;
+}
+
+static inline bool float4_e2m1_is_infinity(float4_e2m1 a)
+{
+ return false;
+}
+
+static inline bool float4_e2m1_is_zero(float4_e2m1 a)
+{
+ return (float4_e2m1_val(a) & 0x7) == 0;
+}
+
+static inline bool float4_e2m1_is_zero_or_denormal(float4_e2m1 a)
+{
+ return (float4_e2m1_val(a) & 0x6) == 0;
+}
+
+static inline bool float4_e2m1_is_normal(float4_e2m1 a)
+{
+ uint8_t em = float4_e2m1_val(a) & 0x7;
+ return em >= 0x2 && em <= 0x7;
+}
+
/*----------------------------------------------------------------------------
| Software half-precision conversion routines.
*----------------------------------------------------------------------------*/
--
2.52.0