mvendorid/marchid/mimplid (mvendorid/marchid MRO, mimplid WARL)

This proposal explores the possibility of adding a "mimplid" (or isamux) CSR that acts as an extra bit of state that goes directly into instruction decoding. It would be analogous to extending every single RISC-V instruction by a few bits so as to guarantee that no conflicts may occur in either custom extensions or future revisions of the RISC-V Standard, as well as permitting processors to execute (rather than JIT decode) completely foreign architectures.

Implementors register (mvendorid-marchid-mimpl) tuples with the FSF gcc and binutils teams, effectively making the FSF the de-facto atomic arbiter responsible for maintaining the world-wide unique encoding database as part of the gcc and binutils codebase.

Conflicting custom extensions thus become world-wide globally unique such that assembly writers, gcc and binutils may have a high to 100% degree of confidence that a given binary will not need recompiling from source, if transferred from one architecture to another (that has the exact same set of extensions).

Ideas discussed so far

One hart, one ISA encoding

This idea is quite straightforward: on any given multi-core processor it can have multiple mvendorid-marchid-mimplid tuples, where each core (hart) has one and only one tuple. Thus, running different encodings is a simple matter of selecting the correct core.

clarification from jacob:

it solves the problem of one implementation needing to implement conflicting extensions, with some limitations, specifically that each of the conflicting extensions must be used in separate threads. The Rocket RoCC coprocessor interface, in a multi-tile SoC where different tiles have different coprocessors, provides a working example of this model. The overall system has both of two conflicting coprocessors.

There are a couple of issues with this approach:

  • Single-core (single hart) implementations are not possible.
  • Multi-core implementations are guaranteed, for high workloads, to have "incompatible" cores sitting idle whilst "compatible" cores are overloaded.

Aside from those limitations it is a workable and valid proposal that has the potential to meet the requirements, that may turn out to be a legitimate and simple and easy to implement subset of other ideas outlined in this document.

Every hart, multiple ISA encodings, mimpl unchanged on traps

This idea allows every hart (core) to have the ability to select any one of multiple ISA encodings, by setting mimpl in U-mode. Implementation-wise the value in mimpl is passed to an out-muxer that generates mutually-exclusive HIGH signals that are passed as an additional input to the selection/enabler blocks of multiple (conflicting) decoders. As an extra signal into the associated multi-input AND gate the overhead is negligeable, and there is no possibility of a conflict due to the out-mux outputs being mutually-exclusive.

Note that whilst this is very similar to setting MISA bits, MISA actively disables instructions from being decoded (whereas whilst the above also disables a certain subset of the opcode space it also enables some in their place). Also - and this is extremely important - it is forbidden for the encoding-switching to alter the actual state of any Extensions (custom or othewise). Changing of mimplid only affects the decoding, it does not, unlike MISA, actually switch on or off the actual Extension and cannot be used to "power down" any hardware.

The tricky bit for this idea is: what happens when a trap occurs, to switch to M-Mode or S-Mode? If this is not taken care of properly there is the possibility for a trap to be running instructions that are completely alien and incompatible with the code and context from which the trap occurred.

A cursory analysis of the situation came to the consensus that whilst in a trap, it would both be highly unlikely that custom opcodes would be used in the trap, or that even when the hart can support multiple approved (present and future) variants of the RV Base Standard, it would be so unusual for RV Base to change between (approved) variants that the possibility of there actually being a conflict is extremely remote. This is good as the code-path in an OS trap (supervisor mode) needs to be kept as short as possible.

However, the possibility that there will be a critical difference cannot be known or ruled out, and foreign ISAs will definitely be made much more difficult to implement full OSes for (particularly proprietary ones) if the M-Mode and S-Mode traps are running an incompatible ISA.

So the solution here is that whenever M-mode changes the mimplid/isamux CSR, the underlying hardware switches mtvec, stvec and bstvec over to separate and distint entries (stored on a per-hart, per-mimplid basis). In the context of there being an OS, the OS would need to be running in a "default" initial context. It would set up mtvec, stvec (and bstvec if required), then change the mimplid/isamux, and set up new mtvec etc. entries as appropriate for that particular (alternative) ISA (including if it is a foreign architecture).

I agree.. complete renumbering is a huge overhead. Guy's solution avoids that overhead and provides a fast-switching mechanism. We had already identified what happens on traps, flushes, caches, etc. Would prefer if we could review/critique that proposal.

If someone wants to re-number the entire custom ISA even then Guy's solution will stand. Plus, in the heterogenous envrionemt, considering each hart/core has its own marcselect(mutable csr), the M mode (or user/supervisor) can simply choose to enable that hart/core by writing to the marchselect CSR.

For compliance, yes we will need Jacob's idea of having a global database somewhere. Also, I believe that the compliance will check only if the core is RISC-V compliant and not worry about any other extensions present or not.

By adding a new mutable csr in the MRW region even existing implementations will be compliant since accessing this CSR in current implementations would just trap.

Every hart, multiple ISA encodings, mimpl set to "default" on traps

This is effectively the same as the above except that when switching to M-Mode or S-Mode, the ISA encoding is always automatically switched to one and only one (default) ISA encoding. There are no complications for the hardware, however for software - particularly OSes and in particular for running foreign hardware ISAs - every single trap now has to work out which ISA the U-mode was running, and branch accordingly. Running a foreign OS thus becomes extremely challenging, although a case could be made for the foreign ISA having its own entirely different orthogonal trap-handling system.

Every hart, multiple ISA encodings, mimpl set to "supervisor-selectable"

This is again identical as far as mimplid/isamux is concerned, with, again, a different kind of decision-making on traps. It was pointed out that if the mimplid/isamux is left unaltered when a trap occurs, switching over from one ISA to another inside a trap and dropping down to a different ISA in U-Mode is made slightly challenging by virtue of the fact that, when the trap changes the ISA, from that point onwards it has to run that ISA inside the trap. This may involve extra code-paths (branches) to require multiple different exit points from the trap.

Whilst again it is quite unlikely that this scenario will arise (due to it being unlikely that the Base ISA will change significantly between (stable, approved) revisions to the RV Standard, the possibility cannot entirely be ruled out.

So this idea is a hybrid of the above two: there is a default ISA for M-Mode and S-Mode, however in each it is possible to set that default.

The idea has not yet been fully analysed and needs further discussion.