mvendorid/marchid WARL

This proposal is to make the mvendorid and marchid CSRs have WARL (writeable) characteristics as a means and method of providing RISC-V implementations with a way to support multiple binary instruction encodings simultaneously within the same processor. Each unique tuple (including on a per-hart basis) uniquely identifies and permits switch-over to a completely separate and distinct binary-encoding such that:

  • Different versions (legacy and new) of the RISC-V Standard may be supported within the same processor
  • The fight over the extremely limited custom opcode space ends (permanently)
  • Entirely foreign ISA may be supported within the same processor (actually executed: i.e. not the same thing at all as the JIT Extension).

For instances where mvendorid and marchid are readable, that would be taken to be a Standards-mandatory "declaration" that the architecture has no Custom Extensions (and that it conforms precisely to one and only one specific variant of the RISC-V Specification).

Beyond that, the change is so simple and straightforward that there is not much to discuss aside from its feasibility and its implications. The main considerations are:

  • State information. How is state to be handled?
  • Compliance. What impact does the change have on Compliance (and testing)?
  • Implementation. Is it feasible and practical?
  • Exception-handlling. What happens during a trap?
  • Backwards compatibility. Is the change zero-impact (for existing systems)
  • Forwards compatibility. Does the change affect (limit) future hardware?

State information

Unlike with MISA (which can be used to completely switch off - i.e. power down) certain Extensions, state information is not permitted to be altered or destroyed during or by a switch-over. Switch-over to a different mvendorid-marchid tuple shall have the effect of purely disabling certain instruction encodings and enabling others.

Note also that during (for example) standard OS context-switching all state of all enabled extensions (and variants of the Base Standards) related to all mvendorid-marchid tuples will need to be saved onto the stack, given that a hart may, at any time, switch between any available mvendorid-marchid tuples.

In other words there is absolutely zero connection of any kind whatsoever between the "encoding switching" and the state or status of the Extensions that the binary encodings are being directed at (on any upcoming conflicting instruction encodings). If a program requires the enablement or disablement of an Extension it uses MISA and other official methods to do so that have absolutely nothing to do with what mvendorid-marchid is presently enabled.

Compliance

It was pointed out early in the discussions that Compliance Testing may fail any system that has mvendorid/marchid as WARL. This however is a clear case of "Compliance Tail Wagging Standard Dog". However it was recognised that overly complex Compliance Testing would result in rejection of the entire RISC-V Standard.

A simple solution is to modify the Compliance Test Suite to specify the required mvendorid/marchid to be tested, as a parameter to the test applications. The test can be run multiple times, providing the implementor with multiple Compliance Certificates for the same processor, against different variants of past, present and future RISC-V Standards.

This is clearly a desirable characteristic

It's been noted that there may be certain legitimate cases where a mvendorid-marchid should specifically not be tested for RISC-V Certification Compliance: native support for foreign architectures (not related to the JIT Extension: actual full entire non-RISC-V foreign instruction encoding). Exactly how this would work (vis-a-vis Compliance) needs discussion, as it would be unfortunate and undesirable for a hybrid processor capable of executing more than one hardware-level ISA support to not be permitted to receive RISC-V Certification Compliance.

How such foreign architectures would switch back to RISC-V when the foreign architecture does not support the concept of mvendorid-marchid is out of scope and left to implementors to define and implement equivalent functionality.

Implementation

The redirection of meaning of certain binary encodings to multiple engines was considered extreme, eyebrow-raising, and also (importantly) potentially expensive, introducing significant latency at the decode phase.

However, it was observed that MISA already switches out entire sets of instructions (interacts at the "decode" phase). The difference between what MISA does and the mvendor/march-id WARL idea is that whilst MISA only switches instruction decoding on (or off), the WARL idea redirects encoding, effectively to different simultaneous engines, fortunately in a deliberately mutually-exclusive fashion.

Implementations would therefore, in each Extension (assuming one separate "decode" engine per Extension), simply have an extra (mutually-exclusively enabled) wire in the AND gate for any given binary encoding, and in this way there would actually be very little impact on the latency. The assumption here is that there are not dozens of Extensions vying for the same binary encoding (at which point the Fabless Semi Company has other much more pressing issues to deal with that make resolving binary encoding conflicts trivial by comparison).

Also pointed out was that in certain cases pipeline stalls could be introduced during the switching phase, if needed, just as they may be needed for correct implementation of (mandatory) support for MISA.

Exception Handling (traps) and context-switching

In cases where mvendorid and marchid are WARL, the mvendorid-marchid becomes part of the execution context that must be saved (and switched as necessary) just like any other state / CSR.

When any trap exception is raised the context / state must not be altered (so that it can be properly saved, if needed, by the exception handler) and that includes the current mvendorid-marchid tuple. This leads to some interesting situations where a hart could conceivably be directed to a set of trap handler binary instructions that the current mvendorid-marchid setting is incapable of correctly interpreting.

To fix this it will be necessary for implementations (hardware / software) to set up separate per-mvendorid-marchid trap handlers and for the hardware (or software) to switch to the appropriate trap "set" when the mvendorid-marchid is written to. The switch to a different "set" will almost undoubtedly require (transparent) hardware assistance.

The reason for requiring hardware-assist for switching exception handling tables is because it has to be done atomically: there cannot be a situation where just as a hart is switching to a different mvendorid-marchid tuple an exception occurs, resulting in execution of effectively foreign instructions.

In essence this means that mtvec needs to be a multi-entry table, one per (mvendorid-marchid) tuple. Likewise stvec, and bstvec.

Backwards-compatibility

Backwards compatibility is vital for Standards. There are two aspects to this:

  • The actual change to the Standard should be minimally-disruptive
  • There should be no interference between two different encodings (any two separate tuples).

Given that mvendorid and marchid are presently read-only; given that the change is to the wording and does not add any new CSRs; the change can clearly be seen to be zero-impact, with the exception being to implementors that have Custom Extensions in silicon at the moment.

On the second point: the entire purpose of the change is to provide globally world-wide irrevocable permanent distinction and separation between instruction encodings!

Forwards-compatibility

Forwards compatibility is again vital for Standards. Standards are required to adapt, yet at the same time provide a means and method of identifying and separating older (and legacy) systems from present and future versions.

The clear separation which mutually-exclusively redirects encodings based on which mvendorid-marchid tuple is currently active clearly meets that requirement.

How the "custom extension conflict" is solved

  • Vendor 1 produces a Custom Extension
  • Vendor 2 produces a Custom Extension
  • Both Custom Extensions have conflicting binary encodings.
  • Fabless Semi Company 1 licenses both Vendor 1 and 2 Custom Extensions
  • Fabless Semi Company 1 sets marchid=0xeee1 WARL to represent enabling Vendor 1's conflicting encoding
  • Fabless Semi Company 1 sets marchid=0xeee2 WARL to represent enabling Vendor 2's conflicting encoding
  • Fabless Semi Company 1 contacts the FSF, submitting patches to gcc (and likewise with binutils) to register (mvendorid=fabless1,marchid=0xeee1) to be added to the global (FSF-curated?) database for Vendor 1's instruction encoding.
  • Likewise for Vendor 2's instruction encoding.

Note that the RISC-V Foundation is not involved (or consulted) in this process. The FSF (as the Copyright holder of gcc and binutils) inherently and implicitly becomes the de-facto atomic arbiter in control of the registration of Custom Extension instruction encodings.

The FSF's "job" is however quite straightforward: ensure that all registrations are in fact unique. It would be absolutely no good if a Vendor decided to re-use two mvendorid-marchid tuples to mean two totally different sets of instructions needed to be enabled! Any Vendor attempting to do so should be red-flagged immediately.

Situations in which the FSF receives requests for patches with another fabless semiconductor company's mvendorid should also be treated with suspicion, at the very least being queried as to why one fabless semi company is trying to encroach on another company's JEDEC-registered encoding space.

The special case of the above is when a fabless semiconductor company implements a new version of the RISC-V Standard. Here, again, the fabless semi company will provide patches to gcc and binutils, requesting that their specific mvendorid-marchid tuple be added to the (inherently de-facto atomic arbitrated) global database for that particular RISC-V Standard "Variant".

Questions to be resolved

  • Can the declaration (meaning) of read-only be expanded to cover any number of (non-conflicting) Custom Extensions? What are the implications of doing so?