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

mstatus cleanup #683

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

Conversation

radimkrcmar
Copy link
Contributor

This series started by noticing that we use SXL in RV32 mode, which results in very ugly accessors for mstatus. The code around mstatus can be improved by changing the architecture (XLEN) detection.

There is (should be) no functional change.

@arichardson
Copy link
Collaborator

Thanks for this change, I haven't had a detailed look at it yet but it seems some of the changes conflict with https://github.com/riscv/sail-riscv/pull/652/files which will most likely be merged soon.

@Timmmm could you take a look and see which one is better or if we want both changes?

@radimkrcmar
Copy link
Contributor Author

The pull request also expands the status to bits(64) and explicitly copies the fields, so I can drop 4 patches. I will rebase when it lands and add 2 patches to clean up its handling of SXL/UXL and SD.

@Timmmm Timmmm self-requested a review January 14, 2025 12:23
@radimkrcmar
Copy link
Contributor Author

I rebased on top of #652 and noticed a bug in it, so this isn't just a cleanup anymore, but introduces a software observable change.

@Timmmm
Copy link
Collaborator

Timmmm commented Jan 28, 2025

Ah what's the bug? Can we fix that quickly in another PR?

@radimkrcmar
Copy link
Contributor Author

The patch fixing it is dc3e3c0. In short, mstatush contains 0b01 in SXL and UXL fields instead of required 0b00.

To fix it quickly, we could replace the SXL/UXL bits with zeros in mstatush accessors, but I don't think we have to rush, because software should ignore those WPRI bits.

@jrtc27
Copy link
Collaborator

jrtc27 commented Jan 28, 2025

They're also supposed to be 0 if the corresponding privilege mode isn't implemented

@radimkrcmar
Copy link
Contributor Author

They're also supposed to be 0 if the corresponding privilege mode isn't implemented

Good point. I didn't really want to change any software-visible behavior in this PR, so I'll add the extensionEnabled in another PR.

@radimkrcmar
Copy link
Contributor Author

I noticed that I didn't commit my last change, so the reset patch was only correct if mstatus was pre-initialized with zeros... It makes no difference, because we have to zero WPRI, but it's still not a good practice.
The force push just removes the last patch, because it would conflict with the reset PR (#597) anyway.

@Timmmm Timmmm mentioned this pull request Jan 29, 2025
Copy link

github-actions bot commented Jan 29, 2025

Test Results

392 tests  ±0   392 ✅ ±0   1m 19s ⏱️ -1s
  1 suites ±0     0 💤 ±0 
  1 files   ±0     0 ❌ ±0 

Results for commit 27f6296. ± Comparison against base commit 8ca0ac0.

♻️ This comment has been updated with latest results.

@Timmmm
Copy link
Collaborator

Timmmm commented Jan 29, 2025

LGTM but I think this could be split into several basically independent PRs which would make it a lot easier to review (and give us nicer history). E.g.

PR 1:
sys_regs: rename cur_Architecture to cur_architecture
types: simplify architecture return type
types: turn architecture into a mapping

PR 2:
insts_base: ignore architecture in SFENCE_VMA

PR 3:
sys_regs: fix RV32 detection in cur_architecture
sys_regs: remove SXL and UXL accessors

PR 4:
sys_regs: compute mstatus and sstatus SD bit on CSR read

PR 5 (these could also be separate PRs but that's probably overkill):
sys_regs: fix SXL and UXL fields in RV32 mstatush
sys_regs: legalize UXL and SXL mstatus fields

Sorry I know it's a bit of a pain! Especially because Github doesn't really support the stacked patch development workflow...

I'll hold off on #597 until all these are merged.

@Timmmm Timmmm mentioned this pull request Jan 29, 2025
@radimkrcmar
Copy link
Contributor Author

LGTM but I think this could be split into several basically independent PRs which would make it a lot easier to review (and give us nicer history). E.g.

Will do, although history will be the same. Please don't tell me you want to squash all the patches. :)

Sorry I know it's a bit of a pain! Especially because Github doesn't really support the stacked patch development workflow...

No worries, this will be quick and easy compared to all the reshuffling I already did.

Especially because Github doesn't really support the stacked patch development workflow...

I think Github supports it (Git alone does), both rebase and merge-commit PR resolution should get you the desired result if you merge the PRs in order.

I'll hold off on #597 until all these are merged.

I would actually prefer to have that one merged first.
It will allow me to end up with cleaner code and more other PRs can depend on it.

@arichardson
Copy link
Collaborator

LGTM but I think this could be split into several basically independent PRs which would make it a lot easier to review (and give us nicer history). E.g.

Will do, although history will be the same. Please don't tell me you want to squash all the patches. :)

I agree that in cases where the history is nice and clean we should use rebase or merge instead of squash

@Timmmm
Copy link
Collaborator

Timmmm commented Jan 29, 2025

Please don't tell me you want to squash all the patches. :)

Nope!

I think Github supports it (Git alone does), both rebase and merge-commit PR resolution should get you the desired result if you merge the PRs in order.

Yeah I mean it doesn't really have a concept of saying "this PR depends on this other PR, so don't show that one". Apparently some source hosting systems do support that (Gerrit maybe?)

I would actually prefer to have that one merged first.

Ok! I'll fix the initial SXL/UXL for RV32 in that one at least.

@radimkrcmar
Copy link
Contributor Author

Yeah I mean it doesn't really have a concept of saying "this PR depends on this other PR, so don't show that one". Apparently some source hosting systems do support that (Gerrit maybe?)

Right, Github just compares the two branches. We would have to work around that by using a range on commits, e.g. https://github.com/riscv/sail-riscv/pull/683/files/cf121a0..ddd0c7f

architecture doesn't change the behavior, so there is no reason to
complicate the code with it.

The code is still suboptimal because of rhs duplication, so this should
be rewritten if (when) Sail supports multiple matches like:
  User    or (Supervisor if mstatus[TVM] == 0b1) => ...
  Machine or (Supervisor if mstatus[TVM] == 0b0) => ...

(Separately mapping those four cases into two and matching on the two is
 also an option, but I'm not sure it would be clearer.)

Signed-off-by: Radim Krčmář <rkrcmar@ventanamicro.com>
The SXL and UXL fields are WPRI when MXLEN=32, so we should not confuse
the sail implementation by saying that SXL and UXL is 0b01 on RV32.

Signed-off-by: Radim Krčmář <rkrcmar@ventanamicro.com>
SD bit is read-only and we don't have to store it anywhere, because its
only purpose is to accelerate software after CSR reads.

Remove SD from mstatus and add SD as the most significant bit in CSR
reads
 * to avoid the need to increase mstatus width to bit(128) when
   implementing RV128,
 * to simplify support for dynamic XLEN (no need to move SD in mstatus),
 * to make the code nicer.

Signed-off-by: Radim Krčmář <rkrcmar@ventanamicro.com>
@@ -179,7 +179,7 @@ function satp_to_ppn(satp_val) =
function translationMode(priv : Privilege) -> SATPMode = {
if priv == Machine then Bare
else {
let arch = architecture(get_mstatus_SXL(mstatus));
let arch = if xlen == 32 then RV32 else architecture(mstatus[SXL]);
let mbits : satp_mode = match arch {
RV64 => {
// Can't have an effective architecture of RV64 on RV32.
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 tried to remove the assert(xlen >= 64) in the RV64 match, but Sail didn't compile with this hunk, nor with

let arch = if xlen >= 64 then architecture(mstatus[SXL]) else RV32;
Type error:
riscv_vmem.sail:187.24-28:
187 |        Mk_Satp64(satp)[Mode]
    |                        ^--^
    | Identifier Mode is unbound
    | 
    | Caused by riscv_vmem.sail:187.18-22:
    | 187 |        Mk_Satp64(satp)[Mode]
    |     |                  ^--^ checking function argument has type bitvector(64)
    |     | Failed to prove constraint: 32 == 64

Am I missing some better way to provide this constraint?

Thanks.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Does it work if you change it to if xlen < 64 then RV32 else ...?

Copy link
Collaborator

Choose a reason for hiding this comment

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

Oh wait I can't read... Never mind.

Copy link
Collaborator

@Alasdair Alasdair Feb 8, 2025

Choose a reason for hiding this comment

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

The constraints mostly flow lexically, i.e. from the condition in the if down into the branches. The type-checker isn't smart enough to understand that arch == RV64 implies that branch in a previous if was taken, it's a bit too indirect.

You can use an assert that's always true at runtime just to assert a fact to the type system. Sometimes it's better to do that than to try to re-write the logic.

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.

5 participants