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

Use newtypes for register indices and numbers #617

Open
wants to merge 3 commits into
base: master
Choose a base branch
from

Conversation

nwf
Copy link
Contributor

@nwf nwf commented Nov 16, 2024

In preparation for more seriously tackling #523. This PR...

  1. Changes the definition of regidx and regno to be newtypes and updates all use sites appropriately.
  2. Splits vregidx from regidx (and friends) for Vector (vext) registers, which, AFAIK, are a completely separate set of 32 registers.
  3. Splits fregidx from regidx (and friends) for F/D/Zcd/Zcf/Zfa/Zfh and V (again) extensions. There's a little muss and fuss around the definition to do with Zfinx, but otherwise it's also pretty rote.
  4. Stops some punning in Zicsr and splits the CSR ast ctor into CSRImm and CSRReg.

This was a slog. Most of the changes can be described as "type-directed" and "mechanical" but were all done... er, artisanally, so some more careful review is probably merited. Perhaps best viewed with word diff, not line diff.

The curious are welcome to look at https://github.com/nwf/sail-riscv/tree/202411-eext to see how I think we can properly support E atop this base, and indeed, most of these changes were motivated or directed by that work, but I would like to get this reviewed independently of that shuffling and further refactoring.

Copy link

github-actions bot commented Nov 16, 2024

Test Results

396 tests  ±0   396 ✅ ±0   0s ⏱️ ±0s
  4 suites ±0     0 💤 ±0 
  1 files   ±0     0 ❌ ±0 

Results for commit 000a17c. ± Comparison against base commit 5f4a8e6.

♻️ This comment has been updated with latest results.

@nwf nwf force-pushed the 202411-newtype_regidx branch from a5d9770 to 97a7742 Compare November 16, 2024 05:02
Copy link
Collaborator

@arichardson arichardson left a comment

Choose a reason for hiding this comment

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

Not reviewed the full diff in detail but overall I think this is a nice improvement!

@nwf nwf force-pushed the 202411-newtype_regidx branch from 97a7742 to 8c83f24 Compare December 13, 2024 21:02
@Timmmm
Copy link
Collaborator

Timmmm commented Dec 16, 2024

Is there any chance this could be split up into multiple PRs to make it easier to review? E.g. can the "initial support for E" be a separate PR?

@nwf
Copy link
Contributor Author

nwf commented Dec 17, 2024

I suppose, but GitHub also allows review commit-by-commit and that's as fine a granularity as I think makes sense to split it?

ETA: I thought having the "Initial support for E extension" as part of the stack would help justify the rest of the changes. I'm happy to punt that to a 2nd PR if it'd make getting the first bit in easier.

@jrtc27
Copy link
Collaborator

jrtc27 commented Dec 17, 2024

With Zfinx I'm not sure how good an idea this is, it seems to get messy quickly. Also I can't actually see your E support anywhere, the tip of the linked branch is nwf@359fdd3 but that doesn't add E, only factors I out.

@Timmmm
Copy link
Collaborator

Timmmm commented Dec 17, 2024

Yeah I think I'm happy with the motivation! I think splitting it up has other advantages:

  • More commits can get merged into main, tested by CI, be part of git bisect etc.
  • It's not all or nothing - hopefully we can get some of it merged before all of it is ready, then rebasing etc. is less of a pain if other people are making simultaneous changes.
  • Just a bit easier to keep track and less intimidating IMO.

Could you also split out Simplify Zicsr ast? Actually I think we probably shouldn't do that. It is simpler and totally in the spirit of how it is supposed to work, and in isolation definitely good. Unfortunately there are two future spanners in the works:

  1. CLIC, which adds all sorts of crazy CSRs that act differently depending on whether you use csrrwi or csrrw.
  2. CHERI, which also treats them differently (because csrrwi/c/s can't write metadata). I think it's way more reasonable in CHERI's case. CLIC is just ... lightly thought through.

@nwf nwf force-pushed the 202411-newtype_regidx branch from 8c83f24 to 000a17c Compare December 17, 2024 18:47
This was referenced Dec 17, 2024
@nwf
Copy link
Contributor Author

nwf commented Dec 17, 2024

OK, I've backed this PR back to 000a17c and have raised #645 and #646 with the two other commits to facilitate discussion.

@nwf
Copy link
Contributor Author

nwf commented Dec 17, 2024

With Zfinx I'm not sure how good an idea this is, it seems to get messy quickly. Also I can't actually see your E support anywhere, the tip of the linked branch is nwf@359fdd3 but that doesn't add E, only factors I out.

Sorry, I missed a git add. #646 has the files added.

As to the complexity around Zfinx and E, well... I don't think the sail is going to be that hairy, and I think the improved clarity in the type system at all use sites outweighs a little complexity at the one definition site.

Copy link
Collaborator

@arichardson arichardson left a comment

Choose a reason for hiding this comment

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

I think being explicit here is a nice improvement and it would be good to merge this ASAP so we don't accumulate merge conflicts.

@jrtc27
Copy link
Collaborator

jrtc27 commented Jan 3, 2025

I think being explicit here is a nice improvement and it would be good to merge this ASAP so we don't accumulate merge conflicts.

I'm not sold given Zfinx; this PR introduces some ugliness there. By introducing new types for everything it ends up having to use the wrong explicit type when previously they were all the same and so there was no wrong type.

@nwf
Copy link
Contributor Author

nwf commented Jan 4, 2025

I'm open to suggestions, but the status quo seems somewhat challenging for E support, especially E machines that reuse the resulting voids in the encoding space, without just forking the whole model.

IMHO Zfinx being a model run-time decision is a deliberate type confusion, and it'd have been better for it to be a model compile-time decision, especially since it cannot (AFAICT) be changed after initialization. It's not surprising, then, that it results in some violence to the types. In particular, I think it is acceptable to the specification to have an implementation of E and F and not-Zfinx that has 16 GPRs and 32 FPU registers, which means that regidx and fregidx really ought to be separable newtypes (perhaps of the same underlying type, of course).

Would you, @jrtc27, accept the first commit, or first two commits, in this PR on its own, without the subsequent refinement of (vregidx and) fregidx as a types-as-documentation improvement, even if you disagree with the approach of "statically E with a smaller regidx" that motivated this series of PRs?

@arichardson
Copy link
Collaborator

I think being explicit here is a nice improvement and it would be good to merge this ASAP so we don't accumulate merge conflicts.

I'm not sold given Zfinx; this PR introduces some ugliness there. By introducing new types for everything it ends up having to use the wrong explicit type when previously they were all the same and so there was no wrong type.

Can't we solve the zfinx problem by adding an explicit conversion? IMO you're still using a freg index in the instruction, it just happens to be mapped to a for internally?

I also think it's odd this is a runtime option an IMO would be cleaner as compile time.

@nwf
Copy link
Contributor Author

nwf commented Jan 4, 2025

Can't we solve the zfinx problem by adding an explicit conversion? IMO you're still using a freg index in the instruction, it just happens to be mapped to a for internally?

Yeah, fregidx-en are decoded (encdec_freg) and passed through the model until they get to the Zfinx-aware register accessors, [rw]F_or_X_[FDH](), which use fregidx_to_regidx() if they need something to pass to X().

I also think it's odd this is a runtime option an IMO would be cleaner as compile time.

A future PR, perhaps.

@jrtc27
Copy link
Collaborator

jrtc27 commented Jan 6, 2025

I think being explicit here is a nice improvement and it would be good to merge this ASAP so we don't accumulate merge conflicts.

I'm not sold given Zfinx; this PR introduces some ugliness there. By introducing new types for everything it ends up having to use the wrong explicit type when previously they were all the same and so there was no wrong type.

Can't we solve the zfinx problem by adding an explicit conversion? IMO you're still using a freg index in the instruction, it just happens to be mapped to a for internally?

No you're not, you're using an X register, there are no F registers.

I also think it's odd this is a runtime option an IMO would be cleaner as compile time.

The whole intent is to reduce compile-time options and have as much configurable at run time as possible. Having something like Zfinx be compile-time option would completely go against that.

@arichardson
Copy link
Collaborator

I think being explicit here is a nice improvement and it would be good to merge this ASAP so we don't accumulate merge conflicts.

I'm not sold given Zfinx; this PR introduces some ugliness there. By introducing new types for everything it ends up having to use the wrong explicit type when previously they were all the same and so there was no wrong type.

Can't we solve the zfinx problem by adding an explicit conversion? IMO you're still using a freg index in the instruction, it just happens to be mapped to a for internally?

No you're not, you're using an X register, there are no F registers.

That's true, but we can still have a type abstraction for "register index of a floating point value"? For RV32 Zdinx we could even assert that it's always an even index when converting it to a GPR index?

I also think it's odd this is a runtime option an IMO would be cleaner as compile time.

The whole intent is to reduce compile-time options and have as much configurable at run time as possible. Having something like Zfinx be compile-time option would completely go against that.

Reading the spec there is no way to dynamically switch this behaviour at runtime since it seems to be gated on the extension being implemented:

In the standard privileged architecture defined in Volume II, the mstatus field FS is hardwired to 0 if the Zfinx extension is implemented, and FS no longer affects the trapping behavior of floating-point instructions or fcsr accesses.

The misa bits F, D, and Q are hardwired to 0 when the Zfinx extension is implemented.

But that point I don't really care about, I just think being explicit about what type of register we are indexing is still useful.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants