RISC-V: They Should Have Known Better
RISC-V: A Case of Over-Ambition
I am frequently pressed to explain why I dislike RISC-V, and usually, I do so in fragments. The typical response I receive is that I simply "do not understand the brilliance" of the architecture—which, as we know, isn't actually a logical argument.
To avoid repeating myself for the time, I've compiled my grievances here. This serves as a central reference for anyone who wishes to challenge my views with a coherent, detailed counter-argument.
Disclaimer: The opinions expressed here are entirely my own. They do not reflect the views of my employer, any religious entity, or my landlord. My cats were consulted; they were split on the issue and will release their own manifesto shortly.
The Myth of the "Universal" ISA
The primary delusion surrounding RISC-V is the idea that it can be everything to everyone. Proponents claim it will dominate everything from the smallest microcontrollers to the most powerful supercomputers.
This is fundamentally impossible.
The requirements for a high-performance CPU are diametrically opposed to those of a budget-constrained microcontroller. These aren't just differences in how you build the chip (microarchitecture); they are differences in the actual instruction set (architecture).
Divergent Design Goals
I am certain RISC-V will eventually dominate the "dirt-cheap" single-use microcontroller market. It will replace the 8051, which is a bar so low it's practically a speed bump.
The "Cheap Core" Checklist
For these types of cores (used in SD cards, USB sticks, or MP3 players), the priorities are:
- Minimal Size: SRAM and ROM are expensive in terms of die area.
- Low Interrupt Latency: The core mostly just prods registers in custom IP.
- Low Cost: No need for hardware multipliers or dividers.
- No Privilege Separation: No untrusted external code is ever executed.
The Interrupt Failure
Fans will argue that RV32IC (or RV32EC) fits this description perfectly. However, in the only area that actually matters for these cores, RISC-V is objectively worse than its competition.
To even be spec-compliant regarding interrupts, you need RV32I_Zicsr. Without Zicsr, there is no standard way to handle interrupts because you have nowhere to temporarily store a register to save the rest of the state. Without it, you're back to the "weird" territory of the 8051.
The Cost of an Interrupt
Let's calculate the cycles required to save ABI-required registers and jump to a C handler.
The Process:
- Use
CSRRWto stash a register (e.g.,t0) and get a base address for the stack. - Stash the following:
ra,sp,gp,tp,t1-t6, anda0-a7. - Use another
CSRRWto recover and stash the originalt0. - Exit: One
CSRRWto find the address, then 19 loads to restore registers. - Account for the
JALto the handler and theRETback.
The Math: Using LaTeX to represent the overhead:
Compare this to the Cortex-M0:
- Entry: 15 cycles.
- Exit: 12 cycles.
- Bonus: Hardware automatically pushes ABI-clobbered registers, allowing the handler to be written directly in C.
| Architecture | Entry Cycles | Exit Cycles | Total Overhead | Hardware Stacking |
|---|---|---|---|---|
| RISC-V (RV32I) | 20 | 20 | No | |
| RISC-V (RV32E) | 14 | 14 | No | |
| Cortex-M0 | 15 | 12 | Yes |
Even the RV32E (which halves the register count) only brings the cost down to 38 cycles.
Fragmentation as a Solution
The existence of CLIC and various proprietary "fast IRQ" extensions is an admission of failure. The base ISA is so deficient that vendors must invent non-standard silicon just to match a decade-old Cortex-M0. This destroys the very "standardization" RISC-V claims to provide.
Ridiculous Encoding
Even the compressed instructions are problematic. Consider the store offsets:
When storing a word, you have a sane range of to bytes. But look at the byte and halfword stores:
- The instruction for storing a halfword is encoded similarly to a byte store.
- Crucially, it has fewer offset options.
- One bit that
store-byteuses for the offset is simply hardwired to zero in the halfword version.
It could have been used to extend the range to 6, but it wasn't. In contrast, the Cortex-M0 provides offsets of for bytes, for halfwords, and for words. This is a far more logical and useful distribution.
Summary of the Logic
if (isa == RISC_V) {
printf("Waste a bit in the encoding; make interrupts slow.");
} else if (isa == CORTEX_M0) {
printf("Use hardware stacking; optimize offsets.");
}
In short: they had the chance to do it right, but they chose a "one size fits all" approach that fits almost nothing perfectly.