Skip to content
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

Correct fcvtmod.w.d flag generation logic for exp == 31 #442

Merged
merged 2 commits into from
Apr 29, 2024

Conversation

jordancarlin
Copy link
Contributor

@jordancarlin jordancarlin commented Mar 25, 2024

Fixes #388 and fixes #268. fcvtmod.w.d is producing an inexact instead of invalid flag for numbers with an exponent of 31 that are not representable as a two's complement integer (> 2^31 - 1 or < -2^31).

Per #388,

According to the Zfa specification, "Floating-point exception flags are raised the same as they would be for FCVT.W.D with the same input operand." According to the unprivileged specification Table 11.4, the invalid exception should be set for inputs > 2^31 - 1 or < -2^31.

This is resolved by adding an additional check when determining the invalid flag for if the integer is > 2^31 - 1 or < -2^31. A similar approach is currently used by Spike.

@allenjbaum
Copy link
Collaborator

allenjbaum commented Mar 25, 2024 via email

let flags : bits(5) = if (true_exp > 31) then nvFlag()
let max_integer = if sign == 0b1 then unsigned(0x80000000)
else unsigned(0x7fffffff);
let flags : bits(5) = if (true_exp > 31 | unsigned(integer) > max_integer) then nvFlag()
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Merging this into a single condition for the if makes the specification harder to read:

  • the check for an exponent >31 means that we shifted bits out of the integer-part of the fixed-point representation;
  • while the comparison against max_integer checks whether the number is representable.

So I would rahter to write this as

  if true_exp > 31 then nvFlag()
 else if not(is_representable_as_signed32(integer)) then nvFlag()
 ...

Thinking somewhat more about this: could we, when converting this into twos-complement, handle this by producing a 33bit intermediate result and checking whether that intermediate result fits into 32bit?
This would remove the need to set the max_integer limit...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The switch to two different if statements for improved readability sounds good to me. I'll go ahead and make that change. I'm not very familiar with Sail, so I'm not sure about implementing the 33bit intermediate to eliminate max_integer, but I can definitely take a look.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Per your suggestion, I split the check into two conditions to improve readability. I can continue to look into eliminating max_integer tomorrow if we want to go that route.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was unable to find a way to do it without max_integer, but hopefully the intent is pretty clear in the current implementation.

@ptomsich
Copy link
Collaborator

Are you aware of any ACT tests that test this particular case? I suspect not, because no one has complained that Spike vs. Sail are diverged. If that is the case, could you file an ACT issue?

I believe this question was raised in the Spike case already — did it get resolved back then?

@jordancarlin
Copy link
Contributor Author

Are you aware of any ACT tests that test this particular case? I suspect not, because no one has complained that Spike vs. Sail are diverged. If that is the case, could you file an ACT issue?

I believe this question was raised in the Spike case already — did it get resolved back then?

There is an open PR to add Zfa (including fcvtmod.w.d) tests. riscv-non-isa/riscv-arch-test/pull/330
The fcvtmod.w.d_b22-01.S test has a case that causes this discrepancy.

inst_34:// fs1 == 1 and fe1 == 0x41e and fm1 == 0xe9b7e5fc9eba4 and  fcsr == 0x0 and rm_val == 7   
/* opcode: fcvtmod.w.d ; op1:f31; dest:x31; op1val:0xc1ee9b7e5fc9eba4; valaddr_reg:x8;
val_offset:10*FLEN/8; rmval:rtz; correctval:??; testreg:x6;
fcsr_val:0*/
TEST_FPID_OP(fcvtmod.w.d, x31, f31, rtz, 0, 0, x8, 10*FLEN/8, x9, x5, x6,FLREG)

@allenjbaum
Copy link
Collaborator

allenjbaum commented Mar 25, 2024 via email

@ptomsich
Copy link
Collaborator

When I look that test up, it has rm=dyn instead of rm=rtz, so I don't know if we are comparing the same thing, or if it makes a difference. I would like to see the smallest number that overflows and the largest that doesn't, and ensure that the correct thing happens with all rounding modes.

fcvtmod.w.d is not defined for rounding modes other than rtz (not that the encoding is selective on 0b001 where the rounding mode field is):

mapping clause encdec = RISCV_FCVTMOD_W_D(rs1, rd)          if haveDExt() & haveZfa()
  <-> 0b110_0001 @ 0b01000 @ rs1 @ 0b001 @ rd @ 0b101_0011  if haveDExt() & haveZfa()

@allenjbaum
Copy link
Collaborator

allenjbaum commented Mar 25, 2024 via email

@ptomsich
Copy link
Collaborator

do you have a pointer to the version that changed dyn to rtz, because the dyn version is the one I found. But, if that's the case, we don't need to check any other rounding modes, and the Sail fix is the only thing that needs changing.

See https://github.com/riscv/riscv-isa-manual/blob/main/src/zfa.adoc

@ptomsich
Copy link
Collaborator

do you have a pointer to the version that changed dyn to rtz, because the dyn version is the one I found. But, if that's the case, we don't need to check any other rounding modes, and the Sail fix is the only thing that needs changing.

See https://github.com/riscv/riscv-isa-manual/blob/main/src/zfa.adoc

From the spec:

This instruction is only provided if the D extension is implemented. It is encoded like FCVT.W.D, but with the rs2 field set to 8 and the rm field set to 1 (RTZ). Other rm values are reserved.

@allenjbaum
Copy link
Collaborator

allenjbaum commented Mar 25, 2024 via email

@jordancarlin
Copy link
Contributor Author

There is an issue with the tests generated in the current version of riscv-non-isa/riscv-arch-test#330. Based on the discussion there, it seems this is a known issue with riscv-ctg right now. There was a version that had rtz at some point, but I can't seem to find it now.

@cmuellner
Copy link

I fixed the CFG in riscv-ctg to reliably generate rtz tests for fcvtmod.
Further, I've regenerated the tests and updated the arch tests PR.

@jordancarlin
Copy link
Contributor Author

ACT tests have been updated and the proposed code change was modified to improve readability.
This is ready to review and hopefully merge.

Copy link

github-actions bot commented Apr 8, 2024

Test Results

712 tests  ±0   712 ✅ ±0   0s ⏱️ ±0s
  6 suites ±0     0 💤 ±0 
  1 files   ±0     0 ❌ ±0 

Results for commit 2921faf. ± Comparison against base commit 495b52c.

♻️ This comment has been updated with latest results.

@davidharrishmc
Copy link

I'd love to get this into Sail so that riscof stops throwing errors on fcvtmod.w.d. Is there anything that still needs to be resolved to accept this PR?

@billmcspadden-riscv
Copy link
Collaborator

We need to have at least 2 people (not the author) review and approve this PR.

@Alasdair
Copy link
Collaborator

I'm not a floating point expert but this looks good to me, and it appears to fix a real problem with the current behaviour others are having.

@davidharrishmc
Copy link

I'm not a Sail expert, but the math agrees with Spike.

@Alasdair Alasdair self-requested a review April 22, 2024 13:59
@jordancarlin
Copy link
Contributor Author

Seems like we're starting to get some reviews (both formal and not) on this. Would love to get this merged so that these issues can be resolved. @billmcspadden-riscv

@Alasdair
Copy link
Collaborator

@billmcspadden-riscv, We didn't get to it in the meeting but I think this and a bunch of other small fix PRs are waiting to be merged.

Copy link
Collaborator

@billmcspadden-riscv billmcspadden-riscv left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@billmcspadden-riscv billmcspadden-riscv merged commit c5ee87d into riscv:master Apr 29, 2024
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
7 participants