proj-plbook-plChRiscvIsa

RISC-V

open source

clearest concise summary of major opcodes is in tables at the end of http://www.eecs.berkeley.edu/Pubs/TechRpts/2014/EECS-2014-146.pdf

younger than (2010) and claims to have learned from SPARC V8 (1994) and OpenRISC? (2000).

http://riscv.org/

http://riscv.org/download.html#tab_isaspec (base opcode listing in Chapter 8)

I'm not sure what addressing modes are supported, but i'm guessing it's non-uniform, with different opcodes for different modes, and mostly register, except for the 'immediate' opcodes which have an 'immediate' component, and loads and stores which have a base+offset mode, with base address in register rs1. Unconditional jumps have PC-relative addressing.

interesting comparison of RISC-V with Epiphany (the one used in Parallella) http://www.adapteva.com/andreas-blog/analyzing-the-risc-v-instruction-set-architecture/

note: RISC-V instructions that the Epiphany guy thought maybe could have been left out:

AUIPC (but in the comments a RISC-V guy says AUIPC was important for relocatable code), SLT/SLTI/STLU/SLTIU (compare: set-less-than, with unsigned and immediate and unsigned immediate variants), XORI/ORI/ANDI (boolean logic with immediate values), FENCE (mb; sync threads), MULH/MULHSU/MULHU (multiply variants with the 'upper half' variant), FSGNJ/FSGNJN/FSGNJX (Sign Inject: Sign source), FCLASS (Categorization: Classify Type). Then there was a bunch for which he said "Not needed for epiphany", which i dunno if he means 'this is good but since Epiphany had a restricted use case target (DSP) we didn't include it'. These are: FLW/FSW (load/store 'W'; i didn't note this below), FMV.X/FMV.S (move from/to integer), FRSCSR (typo? read status regs? i didn't note this below), FSRM/FSRMI (swap rounding mode; i didn't note this below), FSFLAGS (swap flags; i didn't note this below). Then there are some for which he said and 'Needed?', these are: FNMSUB (Negative Multiply-SUBtract), FMIN/FMAX (min/max), FCMP (i can't find this in the table in http://www.eecs.berkeley.edu/Pubs/TechRpts/2014/EECS-2014-146.pdf , so i didn't note this below).

Epiphany instructions that the Epiphany said RISC-V left out that are good: LDRD (load/store double), LDR and STR with the POSTMOD addressing mode (postincrement).

RISC-V has a choice of 16 or 32 integer registers (32 is more typical, i think?) and also optionally, 32 additional floating point registers. Memory is addressed as 8-bit bytes. The instruction encoding is 32-bit, but the 'Compressed' instruction encoding has 16-bit instructions. Instructions tend to have 32-bit, 64-bit, and 128-bit variants; arithmetic is done in at least 32-bit width ("RISC-V can load and store 8 and 16-bit items, but it lacks 8 and 16-bit arithmetic, including comparison-and-branch instructions." [7] ). Register 0 is constant 0.

RISC; no indirect or memory-memory addr modes, but instead there are LOAD and STORE instructions. No autoincrement addr modes. Some opcodes indicate immediate addr mode, others indicate register direct. Little-endian. Branching is compare-and-branch. Variable-length encoding.

"The RISC-V ISA has been designed to include small, fast, and low-power real-world implementations,[2][3] but without over-architecting for a particular microarchitecture style." [8]

"the RISC-V instruction set is designed for practicality of implementation, with features to increase a computer's speed, while reducing its cost and power use. These include placing most-significant bits at a fixed location to speed sign-extension, and a bit-arrangement designed to reduce the number of multiplexers in a CPU." [9]

"RISC-V intentionally lacks condition codes, and even a carry bit.[3] The designers claim that this can simplify CPU designs by minimizing interactions between instructions.[3] Instead RISC-V builds comparison operations into its conditional-jumps.[3] Use of comparisons may slightly increase its power use in some applications. The lack of a carry bit complicates multiple-precision arithmetic. RISC-V does not detect or flag most arithmetic errors, including overflow, underflow, and divide by zero.[3] RISC-V also lacks the "count leading zero" and bit-field operations normally used to speed software floating-point in a pure-integer processor." [10]

" A load or store can add a twelve-bit signed offset to a register that contains an address. A further 20 bits (yielding a 32-bit address) can be generated at an absolute address.[3]

RISC-V was designed to permit position-independent code. It has a special instruction to generate 20 upper address bits that are relative to the program counter. The lower twelve bits are provided by normal loads, stores and jumps.[3] " [11]

" RISC-V does define a special set of integer multiplication instructions. This includes a recommended sequence of instructions that a compiler can generate and a CPU can interpret to perform a fused multiply-accumulate operation. Multiply-accumulate is a core primitive of numerical linear algebra, and so is incorporated as part of a common benchmark, Coremark.[3][15] " [12]

Tutorials:

Retrospectives

Risc-V Compressed (16-bit encoding) opcodes

From [13] (Draft version 1.9):

Summary of Risc-V Compressed (16-bit encoding) opcodes

MOVs and loads and stores and LOADK:

Jumps and branches:

Other stack-pointer-related:

Arithmetic and boolean logic:

Misc:

Details of Risc-V Compressed (16-bit encoding) opcodes

Variants are bit-width and integer vs. floating-point (there are (optional) floating-point registers in RISC-V).

C.(F)L(W

C.(F)S(WC.(F)L(WC.(F)S(W
DQ)SP: Load value from stack (stack-pointer + 6-bit offset) into register. (there is no FLQSP though)
DQ)SP: Store value from register to stack (stack-pointer + 6-bit offset). (there is no FSQSP though)
DQ): Load value from memory (memory address in a register, plus a 5-bit immediate offset) into register (there is no FLQ though)
DQ): Store value from register into memory (memory address in a register, plus a 5-bit immediate offset) (there is no FSQ though)

C.J: Jump to offset given as an immediate constant (PC-relative, signed 11-bit, +-2k range (so +-1k instructions) C.JAL: Like C.J but also writes the current PC (plus 1 instruction) to the link register. C.JR: Jump to PC-relative offset given by register. C.JALR: Like C.JR but also writes the current PC (plus 1 instruction) to the link register.

C.BEQZ: Branch if the value in the given register zero. Offset is signed 8-bit, +-256 (so +-128 instructions). C.BNEQZ: Like C.BEQZ but branch if NOT zero.

C.LI: Load 6-bit immediate into register. C.LUI: Load 6-bit immediate into bits 17-12 of register.

C.ADDI(W): Add 6-bit immediate to register (mutating the register) C.ADDI16SP: Scale 6-bit immediate by 16 then add to stack-pointer (mutating the stack pointer). "used to adjust the stack pointer in procedure prologues and epilogues". C.ADDI4SPN: Scale 8-bit immediate by 4, add to stack pointer, and write the result to register. "used to generate pointers to stack-allocated variables".

C.S(L

R)(LA)I (logicalarithmetic) (leftright)-shifts a register (mutating it) (6-bit immediate shift amount). These variants have a non-uniform scheme for interpreting the immediate to allow it to be most useful. (there is no SLAI though)

C.ANDI is bitwise AND of a register and a 6-bit immediate (mutating the register).

C.MV is register-register MOV.

C.(ADD

SUB)(W) addssubtracts two registers and writes the result over one of the input registers.

C.AND, C.OR, C.XOR is bitwise AND of two registers, writing the result over one of the input registers.

C.BAD, the all-zero instruction, is illegal (not mnemonic is given, i made up 'BAD')

C.NOP is NOP

C.EBREAK breaks into the debugging environment.

Base instructions (32-bit encoding)

from https://content.riscv.org/wp-content/uploads/2017/05/riscv-spec-v2.2.pdf ; see also http://www.eecs.berkeley.edu/Pubs/TechRpts/2014/EECS-2014-146.pdf or https://www.cl.cam.ac.uk/teaching/1617/ECAD+Arch/files/docs/RISCVGreenCardv8-20151013.pdf although they have an older version of the ISA:

Multiply-divide extension ('M') instructions

from https://content.riscv.org/wp-content/uploads/2017/05/riscv-spec-v2.2.pdf or http://www.eecs.berkeley.edu/Pubs/TechRpts/2014/EECS-2014-146.pdf :

(note: the Epiphany guy thought the 'upper half' multiply variants could have been left out)

(mul, mulh, mulhsu, mulhu, div, divu, rem, remu)

Floating-point extension ('F') instructions

from https://content.riscv.org/wp-content/uploads/2017/05/riscv-spec-v2.2.pdf or http://www.eecs.berkeley.edu/Pubs/TechRpts/2014/EECS-2014-146.pdf :

Load and store:

Arithmetic

Mul-Add:

Move (note: the Epiphany guy thought these could have been left out):

Sign Inject (note: the Epiphany guy thought these could have been left out):

Min/Max (note: the Epiphany guy thought these could have been left out):

Compare:

Convert:

Categorization (note: the Epiphany guy thought these could have been left out):

Configuration instructions (read/write the Floating-Point Control and Status Register, fcsr):

Configuration pseudo-op instructions:

(flw fsw fadd fsub fmul fdiv fsqrt fmadd fmsub fnmsub fnmadd fmv.w.x fmv.x.w fsgnj fsgnjn fsgnjx fmin fmax feq flt fle fcvt.s.w fcvt.s.wu fcvt.w.s fcvt.wu.s fclass frcsr fscsr frrm fsrm fsrmi frflags fsflags fsflagsi)

Atomicity extension opcodes

from http://www.eecs.berkeley.edu/Pubs/TechRpts/2014/EECS-2014-146.pdf :

suggested register usage

-- [14]

RISC-V interrupts

" In this second RISC-V article I talk about its interrupt and exception system and about SiFive‘s? FE310G, the first commercial silicon implementation of a RISC-V ...

RISC-V ISA defines two major interrupt types: global and local. Basically, global interrupts are designed for multicore environments, while local interrupts are always associated with one specific core. Local interrupts suffer less overhead as there is no need for arbitration (which is the case of global interrupts on multicore systems).

...

Local interrupt system is responsible for processing a limited (and usually small) number of interrupt sources. The CLINT (Coreplex Local Interrupts) module has three basic interrupt sources: software interrupt (SI), timer interrupt (TI) and external interrupt (EI). RISC-V ISA also defines sixteen other optional local interrupt sources (which are not present on E31). One important note: all global interrupts from PLIC (Platform-level Interrupt Controller) are applied to the external interrupt input within CLINT!

RISC-V interrupt system will suspend execution flow and branch to an ISR if a local interrupt source (as long as it is previously enabled) sets its pending interrupt flag. There is also a global interrupt enable bit (MIE/SIE/UIE according to the current mode) available on MSTATUS register. This register also controls interrupt nesting, memory access privileges, etc. For further information regarding take a look at the RISC-V privileged instructions manual.

There are two ways to deal with interrupts on RISC-V: by using a single vector or multiple vectors. On the single vector mode, register MTVEC (CSR number 0x305) points to the ISR base address, that is, MTVEC points to the single/unique entry point for all ISR code. On the multiple vector mode, on the other hand, MTVEC works as a pointer to the vector table base address and the index for that table is taken from the MCAUSE register (CSR number 0x342). " [15]

RISC-V variants

DarkRiscV subset

I think it contains:

Note that it does not contain the fence*, e*, and csr* instructions (memory fences, privilege levels and configuration registers). I believe that it also omits the SCALL, SBREAK, and the counter (RD*) instructions. The above instructions are all of the RV32I instructions except for these omissions.

RISC-V links

RISC-V discussion

"

Lack of execute-only/read-only memory

" tropo 51 days ago [-]

Security:

It still won't do execute-only and true read-only memory. We've had true read-only for ages now on x86, and just got execute-only. You need these: rw- r-- --x

It still has poor support for ASLR, especially the limited-MMU variants. Even the most limited version should be able to require that the uppermost address bits be something randomish, even if it's only a per-priv-level random cookie. " -- [16]

Lack of overflow checks

" pizlonator 51 days ago [-]

"We did not include special instruction set support for overflow checks on integer arithmetic operations, as many overflow checks can be cheaply implemented using RISC-V branches."

False. For example, JavaScript? add/sub will require 3x more instructions on RISC-V than x86 or ARM. Same will be true for any other language requires (either implicitly, like JS, or explicitly, like .NET) overflow checking. Good luck with that, lol.

__s 50 days ago [-]

Many overflow checks can be removed with optimization. RISC-V's compressed encoding has shown to be ~70-80% more compact, so it has room for overflow checks. The efficiency of the architecture can always compile it out by time it hits microcode

http://joeduffyblog.com/2015/12/19/safe-native-code

pizlonator 50 days ago [-]

I pioneered most of WebKit?'s overflow check optimizations, and our compiler is bleeding-edge when it comes to eliminating them. Still, the overwhelming majority of the checks remain, because most integer values are not friendly to analysis (because they came from some heap location, or they came from some hard math, etc).

I doubt that the architecture will compile out signed integer addition overflow checks, which are the most common. They are brutal to express correctly without an overflow bit, and the architecture will have a hard time with this.

zxcdw 50 days ago [-]

Why do you suppose they left it out? Is it merely a matter of "cheap implementation" being purely subjective, and hence they might have thought it as cheap, while you seem to disagree? Or could there be a more pressing reason, but "Oh well, its cheap enough anyway" is more of an excuse?

pizlonator 50 days ago [-]

I don't think they knew that modern languages rely on overflow checks so heavily and that the perf of overflow checks dominates perf overall. " -- [17]

Opinions

Overall opinions

http://www.adapteva.com/andreas-blog/analyzing-the-risc-v-instruction-set-architecture/

" There are a lot of things about the RISCV design that come from a very ideological place and hurt in a high end design. Yes, there are extensions and designs with high end features, that's certainly true, and I'm sure people someone will be making a high end version at some point. But the ISA isn't very well suited to it compared to Power or ARM.

By default, code density on RISC-V is pretty bad. You can try to solve that by using variable length instructions which many high end RISC-V projects intend to do but having variable length instructions means your front end is going to have to be more complicated to reach the same level of performance that a fixed width instruction machine can achieve.

More instructions for a task means your back end also has to execute more instructions to reach the same level of performance. One way to do better is to fuse together ISA-level instructions into a smaller number of more complex instructions that get executed in your core. This is something that basically every high end design does but RISC-V would have to do it far more extensively than other architectures to achieve a similar level of density on the back end which makes designing a high end core more complex and possibly uses extra pipeline stages making mispredicts more costly.

And more more criticisms here: https://gist.github.com/erincandescent/8a10eeeea1918ee4f9d9982f7618ef68

EDIT: But in fairness it looks like conditional move might be getting added to the bit manipulation RISC-V extension which would fix one big pain point.

This isn't to say that RISC-V is bad. It's simplicity makes it wonderful for low end designs. It's extensibility makes it great for higher level embedded uses where you might want to add some instruction that makes your life easier for your hard driver controller or whatever in a way that would require a very expensive architecture license if you were using ARM. It's open, which would be great if you were making a high end open-source core for other people to use except the Power ISA just opened up so if I were to start a project like that I'd use that instead. " -- Symmetry

"Aarch64 has more complex addressing modes (base + index<<shift in particular) whereas RISC-V needs both RVC and fusion to do the same with similar code size and execution slot occupation. Personally, I'm leaving towards thinking that it was a mistake for RISC-V to not support such addressing modes. Unless you're aiming for something really super-constrained in terms of gate counts, having an adder and small shifter as part of your memory pipeline(s) seem like an obvious choice. And thus, having single instructions to use those pipelines isn't really committing any sins against the RISC philosophy. " -- jabl

brucehoult 1 day ago [–]

(On ARM) "NEON is guaranteed to exist on everything, and this means you're never going to see Aarch64 replace the Cortex M0 and M3. That's fragmentation right there. Severe fragmentation. Two completely incompatible ISAs. Small 32 bit RISC-V comes in smaller and lower power than An M0, and small 64 bit RISC-V is not much bigger than an M0 and is rather popular controlling something in the corner of a larger 64 bit SoC?." -- brucehoult

Misc opinions