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

Support for RV32E / RV64E #523

Open
rmn30 opened this issue Aug 15, 2024 · 14 comments
Open

Support for RV32E / RV64E #523

rmn30 opened this issue Aug 15, 2024 · 14 comments
Labels
enhancement New feature or request tgmm-agenda Tagged for the next Golden Model meeting agenda.

Comments

@rmn30
Copy link
Collaborator

rmn30 commented Aug 15, 2024

This model currently assumes there are 32 X registers i.e. the "embedded" ISA variants with only 16 registers are not supported.
The CHERIoT fork of this repo includes a bit of a hack to work around this. It raises a Sail exception for the invalid registers in the register access functions then catches it and raises a RISC-V reserved instruction in the instruction fetch loop. This almost works but has a major disadvantage that any side effects of instruction execution that happen before the illegal register access will still take effect! For example if rd of a csrrw is greater than 15 this won't be noticed until the CSR has already been written but it will then a reserved instruction exception!

We could fix this in the decode mapping, for example by adding a guard such as if validXReg(rd) && validXReg(rs1) && validXReg(rs2) on every mapping where validXReg would account for the embedded variants, however this would be very intrusive. I'm posting this to canvas opinion and see if anyone has any better ideas.

@nwf-msr
Copy link

nwf-msr commented Aug 15, 2024

In the existing model, there are two types used to index into registers:

type regidx = bits(5)
type regno = range(0, 31)

These are just bit vectors. The instruction AST just uses these directly

union clause ast = UTYPE : (bits(20), regidx, uop)

and the machine instruction codec mapping function just slice these directly out of the bits:

mapping clause encdec = UTYPE(imm, rd, op)
<-> imm @ rd @ encdec_uop(op)

By contrast, in some other architectural modeling that I've done with sail, I ended up defining an algebraic type for register selectors, gave that a dedicated encoding mapping function, made the instruction AST use the algebraic type, and had the codec mapping appeal to the register selector mapping function. We could rework the RISC-V sail model to use that approach, and if we did it right, models of RV-E could provide a different type and different codecs than models of RV-I.

This is probably more intrusive than the if validXReg(rd) approach in terms of LoC changed, but it's a type directed chore and sail will tell model authors if they're trying to slice out the bits rather than map to a valid register, which the if validXreg(rd) approach will not.

@billmcspadden-riscv
Copy link
Collaborator

billmcspadden-riscv commented Aug 15, 2024 via email

@Alasdair
Copy link
Collaborator

Alasdair commented Aug 15, 2024

Following on from @nwf-msr's comment, if you wanted to make the spec truely parametric in whether the E extension exists or not you could do something like:

type E : Bool

struct regidx = {
  idx : bits(if E then 4 else 5) 
}

mapping xreg : bits(5) <-> regidx = {
  forwards bv if constraint(E) && bv[4] == 0 => struct { idx = bv[3..0] },
  forwards bv if not(constraint(E)) => struct { idx = bv },
  backwards reg => zero_extend(reg.idx),
}

Then the decode clauses would look like e.g.

union clause ast = UTYPE : (bits(20), regidx, uop)

mapping clause encdec = UTYPE(imm, rd, op)
  <-> imm @ xreg(rd) @ encdec_uop(op)

Currently this requires the --abstract-types option for Sail which is quite experimental, and might explode. I've been slowly working on tying this together with the Sail module system, so you can write extensions as Sail optional modules and have types that vary depending whether that extension is present, and you avoid the problem of ifdefs where certain combinations are not statically checked to work.

This is probably more intrusive than the if validXReg(rd) approach in terms of LoC changed, but it's a type directed chore and sail will tell model authors if they're trying to slice out the bits rather than map to a valid register, which the if validXreg(rd) approach will not.

I think the fact that it can be checked would make this approach much better than just having a validXreg guard. I'm not even sure it would be that much more of a chore.

@nwf-msr
Copy link

nwf-msr commented Aug 15, 2024

Following on from @nwf-msr's comment, if you wanted to make the spec truely parametric in whether the E extension exists

Oh, that's very cute. I hadn't imagined something so elaborate and had just imagined swapping out between model/riscv-regs-i.sail and riscv-regs-e.sail.

@Alasdair
Copy link
Collaborator

That's probably the simplest way to handle it right now, but I've been trying to add features to handle some of the RISC-V configurability in a more generic way, but it's not 100% in place yet.

@Timmmm
Copy link
Collaborator

Timmmm commented Aug 15, 2024

have types that vary depending whether that extension is present

Would that require recompiling the Sail code to switch between E and not-E, because you have to include/exclude the E code? I think it would be better (if possible) if we could always compile the E code but make it a "configure time" option (i.e. a parameter to model_init() or similar).

Also why does regidx need to be a struct and not just a type alias?

type regidx = bits(if E then 4 else 5)

@nwf-msr
Copy link

nwf-msr commented Aug 15, 2024

Also why does regidx need to be a struct and not just a type alias?

To strongly encourage, if not quite force, the use of the partial xreg mapping (as in #523 (comment)) in the instruction codec mapping-s, rather than just slicing the register bits out of the instruction bits.

A type alias to the type you suggest seems like it would make slicing somewhat challenging. I think you'd need to replace @ rd @ with @ pad_rd @ rd @ with pad_rd : bits(if E then 1 else 0) and ensure that it was zero. That is, I think the struct type is also more ergonomic despite the additional layer of struct-ure.

@Alasdair
Copy link
Collaborator

Would that require recompiling the Sail code to switch between E and not-E, because you have to include/exclude the E code? I think it would be better (if possible) if we could always compile the E code but make it a "configure time" option (i.e. a parameter to model_init() or similar).

In theory no, but it would require some enhancements to the Sail->C backend to handle a type like bits(if ... then len else other_len) at runtime (which just means representing it as a variable-width bitvector that can handle both lengths, which we already have). Some Sail backends can't handle that so you'd have to instantiate the abstract types with concrete types at compile time.

@billmcspadden-riscv billmcspadden-riscv added the tgmm-agenda Tagged for the next Golden Model meeting agenda. label Aug 19, 2024
@allenjbaum
Copy link
Collaborator

allenjbaum commented Aug 25, 2024 via email

@Timmmm
Copy link
Collaborator

Timmmm commented Aug 26, 2024

It's read-only:

The "I" bit will be set for RV32I, RV64I, and RV128I base ISAs, and the "E" bit will be set for RV32E and RV64E. The Extensions field is a WARL field that can contain writable bits where the implementation allows the supported ISA to be modified. At reset, the Extensions field shall contain the maximal set of supported extensions, and "I" shall be selected over "E" if both are available.

The "E" bit is read-only. Unless misa is all read-only zero, the "E" bit always reads as the complement of the "I" bit. If an execution environment supports both RV32E and RV32I, software can select RV32E by clearing the "I" bit.

Would it be a mistake to not support runtime switching of E, even though the spec does support it (the model already has that limitations for XLEN)?

It obviously makes the code way nicer if it's a compile time option (or "constraint time") and runtime switching of E seems like it would be an extremely niche design.

@allenjbaum
Copy link
Collaborator

allenjbaum commented Aug 30, 2024 via email

@Timmmm
Copy link
Collaborator

Timmmm commented Aug 30, 2024

My preference is that the I bit be readonly; there is no reason I can think of to switch it.

I agree. Do you think you could convince them to specify that?

@allenjbaum
Copy link
Collaborator

allenjbaum commented Aug 30, 2024 via email

@allenjbaum
Copy link
Collaborator

allenjbaum commented Sep 5, 2024 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request tgmm-agenda Tagged for the next Golden Model meeting agenda.
Projects
None yet
Development

No branches or pull requests

6 participants