-
Notifications
You must be signed in to change notification settings - Fork 1
F16 support #1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Draft
lillianrubyrose
wants to merge
23
commits into
HarryR:main
Choose a base branch
from
whisker-emu:f16
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Draft
F16 support #1
Changes from all commits
Commits
Show all changes
23 commits
Select commit
Hold shift + click to select a range
562a834
F16 addition
lillianrubyrose 943a5f5
F16 sub
lillianrubyrose 57f75c8
F16 div
lillianrubyrose 1475d6c
F16 classify
lillianrubyrose 59de77a
F16 eq_signaling
lillianrubyrose 98dc53f
F16 eq
lillianrubyrose 75f60d3
F16 isSignalingNaN
lillianrubyrose bfd4af0
F16 le_quiet
lillianrubyrose 573b36d
F16 le
lillianrubyrose 107fa3c
F16 lt/lt_quiet
lillianrubyrose db6402d
F16 mul
lillianrubyrose a321ba3
F16 mulAdd
lillianrubyrose 860418f
F16 rem
lillianrubyrose 4b99a52
F16 roundToInt
lillianrubyrose acbc258
F16 sqrt
lillianrubyrose 70c61e9
F16 f16_to_f32/f16_to_f64
lillianrubyrose 1d60294
F16 f16_to_i32/f16_to_i64
lillianrubyrose 7d072f3
F16 f16_to_ui32/f16_to_ui64
lillianrubyrose 46252d1
F16 f32_to_f16/f64_to_f16
lillianrubyrose 078cbae
F16 i32_to_f16/i64_to_f16
lillianrubyrose 989789c
F16 ui32_to_f16/ui64_to_f16
lillianrubyrose e8d3eaf
format
lillianrubyrose 8cce208
Inline specific F16 functions
lillianrubyrose File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,94 @@ | ||
| use super::{float16_t, signF16UI, softfloat_addMagsF16, softfloat_subMagsF16}; | ||
|
|
||
| #[inline] | ||
| #[must_use] | ||
| pub const fn f16_add( | ||
| a: float16_t, | ||
| b: float16_t, | ||
| roundingMode: u8, | ||
| detectTininess: u8, | ||
| ) -> (float16_t, u8) { | ||
| if signF16UI(a.v ^ b.v) { | ||
| softfloat_subMagsF16(a.v, b.v, roundingMode, detectTininess) | ||
| } else { | ||
| softfloat_addMagsF16(a.v, b.v, roundingMode, detectTininess) | ||
| } | ||
| } | ||
|
|
||
| #[cfg(test)] | ||
| mod tests { | ||
| use super::*; | ||
|
|
||
| #[test] | ||
| fn test_f16_add() { | ||
| struct softfloat_f16_add_TestCase { | ||
| a: u16, | ||
| b: u16, | ||
| result: u16, | ||
| flags: u8, | ||
| roundingMode: u8, | ||
| detectTininess: u8, | ||
| } | ||
|
|
||
| let cases = [ | ||
| softfloat_f16_add_TestCase { | ||
| a: 0x0000, | ||
| b: 0x3C00, | ||
| result: 0x3C00, | ||
| flags: 0, | ||
| roundingMode: 0, | ||
| detectTininess: 1, | ||
| }, | ||
| softfloat_f16_add_TestCase { | ||
| a: 0x3C00, | ||
| b: 0x3C00, | ||
| result: 0x4000, | ||
| flags: 0, | ||
| roundingMode: 0, | ||
| detectTininess: 1, | ||
| }, | ||
| softfloat_f16_add_TestCase { | ||
| a: 0xBC00, | ||
| b: 0x3C00, | ||
| result: 0x0000, | ||
| flags: 0, | ||
| roundingMode: 0, | ||
| detectTininess: 1, | ||
| }, | ||
| softfloat_f16_add_TestCase { | ||
| a: 0x0000, | ||
| b: 0x0000, | ||
| result: 0x0000, | ||
| flags: 0, | ||
| roundingMode: 0, | ||
| detectTininess: 1, | ||
| }, | ||
| softfloat_f16_add_TestCase { | ||
| a: 0x3800, | ||
| b: 0x3800, | ||
| result: 0x3C00, | ||
| flags: 0, | ||
| roundingMode: 0, | ||
| detectTininess: 1, | ||
| }, | ||
| softfloat_f16_add_TestCase { | ||
| a: 0xBC00, | ||
| b: 0xBC00, | ||
| result: 0xC000, | ||
| flags: 0, | ||
| roundingMode: 0, | ||
| detectTininess: 1, | ||
| }, | ||
| ]; | ||
|
|
||
| for (i, c) in cases.iter().enumerate() { | ||
| let (res, flags) = f16_add( | ||
| float16_t { v: c.a }, | ||
| float16_t { v: c.b }, | ||
| c.roundingMode, | ||
| c.detectTininess, | ||
| ); | ||
| assert_eq!((i, res.v, flags), (i, c.result, c.flags)); | ||
| } | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,23 @@ | ||
| use super::{expF16UI, float16_t, fracF16UI, isNaNF16UI, signF16UI, softfloat_isSigNaNF16UI}; | ||
|
|
||
| #[inline] | ||
| #[must_use] | ||
lillianrubyrose marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| pub const fn f16_classify(a: float16_t) -> u16 { | ||
| let infOrNaN = expF16UI(a.v) == 0x1F; | ||
| let subnormalOrZero = expF16UI(a.v) == 0; | ||
| let sign = signF16UI(a.v); | ||
| let fracZero = fracF16UI(a.v) == 0; | ||
| let isNaN = isNaNF16UI(a.v); | ||
| let isSNaN = softfloat_isSigNaNF16UI(a.v); | ||
|
|
||
| return ((sign && infOrNaN && fracZero) as u16) | ||
| | (((sign && !infOrNaN && !subnormalOrZero) as u16) << 1) | ||
| | (((sign && subnormalOrZero && !fracZero) as u16) << 2) | ||
| | (((sign && subnormalOrZero && fracZero) as u16) << 3) | ||
| | (((!sign && infOrNaN && fracZero) as u16) << 7) | ||
| | (((!sign && !infOrNaN && !subnormalOrZero) as u16) << 6) | ||
| | (((!sign && subnormalOrZero && !fracZero) as u16) << 5) | ||
| | (((!sign && subnormalOrZero && fracZero) as u16) << 4) | ||
| | (((isNaN && isSNaN) as u16) << 8) | ||
| | (((isNaN && !isSNaN) as u16) << 9); | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,213 @@ | ||
| use super::{ | ||
| defaultNaNF16UI, expF16UI, float16_t, fracF16UI, packToF16, packToF16UI, signF16UI, | ||
| softfloat_approxRecip_1k0s, softfloat_approxRecip_1k1s, softfloat_flag_infinite, | ||
| softfloat_flag_invalid, softfloat_normSubnormalF16Sig, softfloat_propagateNaNF16, | ||
| softfloat_roundPackToF16, | ||
| }; | ||
|
|
||
| #[must_use] | ||
| pub const fn f16_div( | ||
| a: float16_t, | ||
| b: float16_t, | ||
| roundingMode: u8, | ||
| detectTininess: u8, | ||
| ) -> (float16_t, u8) { | ||
| let signA = signF16UI(a.v); | ||
| let mut expA = expF16UI(a.v); | ||
| let mut sigA = fracF16UI(a.v); | ||
| let signB = signF16UI(b.v); | ||
| let mut expB = expF16UI(b.v); | ||
| let mut sigB = fracF16UI(b.v); | ||
| let signZ = signA ^ signB; | ||
| if expA == 0x1F { | ||
| if sigA != 0 { | ||
| return softfloat_propagateNaNF16(a.v, b.v); | ||
| } | ||
| if expB == 0x1F { | ||
| if sigB != 0 { | ||
| return softfloat_propagateNaNF16(a.v, b.v); | ||
| } | ||
| return (float16_t { v: defaultNaNF16UI }, softfloat_flag_invalid); | ||
| } | ||
| return (packToF16(signZ, 0x1F, 0), 0); | ||
| } | ||
| if expB == 0x1F { | ||
| if sigB != 0 { | ||
| return softfloat_propagateNaNF16(a.v, b.v); | ||
| } | ||
| return (packToF16(signZ, 0, 0), 0); | ||
| } | ||
| if expB == 0 { | ||
| if sigB == 0 { | ||
| if (expA as u16) | sigA == 0 { | ||
| return (float16_t { v: defaultNaNF16UI }, softfloat_flag_invalid); | ||
| } | ||
| return (packToF16(signZ, 0x1F, 0), softfloat_flag_infinite); | ||
| } | ||
| let normExpSig = softfloat_normSubnormalF16Sig(sigB); | ||
| expB = normExpSig.exp; | ||
| sigB = normExpSig.sig; | ||
| } | ||
| if expA == 0 { | ||
| if sigA == 0 { | ||
| return (packToF16(signZ, 0, 0), 0); | ||
| } | ||
| let normExpSig = softfloat_normSubnormalF16Sig(sigA); | ||
| expA = normExpSig.exp; | ||
| sigA = normExpSig.sig; | ||
| } | ||
| let mut expZ = (expA as i16).wrapping_sub(expB as i16).wrapping_add(0xE); | ||
| sigA |= 0x0400; | ||
| sigB |= 0x0400; | ||
| if sigA < sigB { | ||
| expZ = expZ.wrapping_sub(1); | ||
| sigA <<= 5; | ||
| } else { | ||
| sigA <<= 4; | ||
| } | ||
| let index = (sigB >> 6) & 0xF; | ||
| let r0 = softfloat_approxRecip_1k0s[index as usize].wrapping_sub( | ||
| ((softfloat_approxRecip_1k1s[index as usize] as u32).wrapping_mul((sigB & 0x3F) as u32) | ||
| >> 10) as u16, | ||
| ); | ||
| let mut sigZ = (((sigA as u32).wrapping_mul(r0 as u32)) >> 16) as u16; | ||
| let mut rem = (sigA << 10).wrapping_sub(sigZ.wrapping_mul(sigB)); | ||
| sigZ = sigZ.wrapping_add(((rem as u32).wrapping_mul(r0 as u32) >> 26) as u16); | ||
| sigZ = sigZ.wrapping_add(1); | ||
| if (sigZ & 7) == 0 { | ||
| sigZ &= !1; | ||
| rem = (sigA << 10).wrapping_sub(sigZ.wrapping_mul(sigB)); | ||
| if (rem & 0x8000) != 0 { | ||
| sigZ = sigZ.wrapping_sub(2); | ||
| } else if rem != 0 { | ||
| sigZ |= 1; | ||
| } | ||
| } | ||
| return softfloat_roundPackToF16(signZ, expZ, sigZ, roundingMode, detectTininess); | ||
| } | ||
|
|
||
| #[cfg(test)] | ||
| mod tests { | ||
| use super::*; | ||
|
|
||
| #[test] | ||
| fn test_f16_div() { | ||
| struct softfloat_f16_div_TestCase { | ||
| a: u16, | ||
| b: u16, | ||
| result: u16, | ||
| flags: u8, | ||
| roundingMode: u8, | ||
| detectTininess: u8, | ||
| } | ||
|
|
||
| let cases = [ | ||
| softfloat_f16_div_TestCase { | ||
| a: 0x3C00, | ||
| b: 0x3C00, | ||
| result: 0x3C00, | ||
| flags: 0, | ||
| roundingMode: 0, | ||
| detectTininess: 1, | ||
| }, | ||
| softfloat_f16_div_TestCase { | ||
| a: 0x4000, | ||
| b: 0x3C00, | ||
| result: 0x4000, | ||
| flags: 0, | ||
| roundingMode: 0, | ||
| detectTininess: 1, | ||
| }, | ||
| softfloat_f16_div_TestCase { | ||
| a: 0x3C00, | ||
| b: 0x4000, | ||
| result: 0x3800, | ||
| flags: 0, | ||
| roundingMode: 0, | ||
| detectTininess: 1, | ||
| }, | ||
| softfloat_f16_div_TestCase { | ||
| a: 0x4400, | ||
| b: 0x4000, | ||
| result: 0x4000, | ||
| flags: 0, | ||
| roundingMode: 0, | ||
| detectTininess: 1, | ||
| }, | ||
| softfloat_f16_div_TestCase { | ||
| a: 0xBC00, | ||
| b: 0x3C00, | ||
| result: 0xBC00, | ||
| flags: 0, | ||
| roundingMode: 0, | ||
| detectTininess: 1, | ||
| }, | ||
| softfloat_f16_div_TestCase { | ||
| a: 0x3C00, | ||
| b: 0xBC00, | ||
| result: 0xBC00, | ||
| flags: 0, | ||
| roundingMode: 0, | ||
| detectTininess: 1, | ||
| }, | ||
| softfloat_f16_div_TestCase { | ||
| a: 0xC000, | ||
| b: 0xBC00, | ||
| result: 0x4000, | ||
| flags: 0, | ||
| roundingMode: 0, | ||
| detectTininess: 1, | ||
| }, | ||
| softfloat_f16_div_TestCase { | ||
| a: 0x4200, | ||
| b: 0x4000, | ||
| result: 0x3E00, | ||
| flags: 0, | ||
| roundingMode: 0, | ||
| detectTininess: 1, | ||
| }, | ||
| softfloat_f16_div_TestCase { | ||
| a: 0x0000, | ||
| b: 0x3C00, | ||
| result: 0x0000, | ||
| flags: 0, | ||
| roundingMode: 0, | ||
| detectTininess: 1, | ||
| }, | ||
| softfloat_f16_div_TestCase { | ||
| a: 0x3C00, | ||
| b: 0x7C00, | ||
| result: 0x0000, | ||
| flags: 0, | ||
| roundingMode: 0, | ||
| detectTininess: 1, | ||
| }, | ||
| softfloat_f16_div_TestCase { | ||
| a: 0x7C00, | ||
| b: 0x3C00, | ||
| result: 0x7C00, | ||
| flags: 0, | ||
| roundingMode: 0, | ||
| detectTininess: 1, | ||
| }, | ||
| softfloat_f16_div_TestCase { | ||
| a: 0x3C00, | ||
| b: 0x0000, | ||
| result: 0x7C00, | ||
| flags: softfloat_flag_infinite, | ||
| roundingMode: 0, | ||
| detectTininess: 1, | ||
| }, | ||
| ]; | ||
|
|
||
| for (i, c) in cases.iter().enumerate() { | ||
| let (res, flags) = f16_div( | ||
| float16_t { v: c.a }, | ||
| float16_t { v: c.b }, | ||
| c.roundingMode, | ||
| c.detectTininess, | ||
| ); | ||
| assert_eq!((i, res.v, flags), (i, c.result, c.flags)); | ||
| } | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,13 @@ | ||
| use super::{float16_t, isNaNF16UI, softfloat_flag_invalid, softfloat_isSigNaNF16UI}; | ||
|
|
||
| #[inline] | ||
| #[must_use] | ||
lillianrubyrose marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| pub const fn f16_eq(a: float16_t, b: float16_t) -> (bool, u8) { | ||
| if isNaNF16UI(a.v) || isNaNF16UI(b.v) { | ||
| if softfloat_isSigNaNF16UI(a.v) || softfloat_isSigNaNF16UI(b.v) { | ||
| return (false, softfloat_flag_invalid); | ||
| } | ||
| return (false, 0); | ||
| } | ||
| return (a.v == b.v || ((a.v | b.v) << 1) == 0, 0); | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,10 @@ | ||
| use super::{float16_t, isNaNF16UI, softfloat_flag_invalid}; | ||
|
|
||
| #[inline] | ||
| #[must_use] | ||
lillianrubyrose marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| pub const fn f16_eq_signaling(a: float16_t, b: float16_t) -> (bool, u8) { | ||
| if isNaNF16UI(a.v) || isNaNF16UI(b.v) { | ||
| return (false, softfloat_flag_invalid); | ||
| } | ||
| return ((a.v == b.v) || ((a.v | b.v) << 1) == 0, 0); | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| use super::{float16_t, softfloat_isSigNaNF16UI}; | ||
|
|
||
| #[inline] | ||
| #[must_use] | ||
| pub const fn f16_isSignalingNaN(a: float16_t) -> bool { | ||
| return softfloat_isSigNaNF16UI(a.v); | ||
| } |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I commented these out because a lot of code that wasn't added in this PR (I'm sure tons of what I added here does as well though!) violates various lints in these groups and my editor was screaming lol.
I could fix them in this PR if you'd like, @HarryR , although I think it would be more appropriate for me to do as a follow-up PR.