3 ms·
Is there any published rationale for the RISC-V instruction encoding? A few months back I set out to write a software emulator of RISC-V for fun. I expected th
by haberman 6y ago
Is there any published rationale for the RISC-V instruction encoding?
A few months back I set out to write a software emulator of RISC-V for fun. I expected the instruction set encoding to lend itself well to a very simple implementation, eg. something you could decode in 5-10 lines of C plus some tables.
But the instruction encoding is much more irregular than I expected: https://github.com/ucb-bar/riscv-sodor/blob/master/src/common/instructions.scala https://github.com/ucb-bar/riscv-sodor/blob/master/src/commo...
In particular:
- The bit patterns allocated to the simplest instructions
(eg. rv32i) seem random. Why not allocate starting from zero
to allow dense jump tables?
- I can't make any sense of the groupings. A bunch of instructions
have 0b1100011 in the lowest bits, do these instructions have
something in common?
I assume there is some rhyme and reason to all this? Where is this explained?
- dahfizz 6y agoI agree. I had to write a dissembler for RISC-V in college and it was surprisingly annoying.
- r1sc5away 6y agoI'm not sure about publications that try to answer "why RISC-V?", but the specification often describes the rationales behind many of these kinds of decisions. The bit patterns are often designed to make it easier to write efficient hardware designs to implement them. For example, if an instruction encodes an "immediate" value, the most significant bit of the instruction will always hold that value's sign-extension bit. And if you compare the immediate values in I-/S-/B-/J-type instructions, you can see that bits [5:10] are always in the same place. It's not exactly intuitive, but there is some rhyme and reason. In the base instruction set, the 0b1100011 opcode encodes a set of conditional branch instructions. They perform relative jumps if rs1 == rs2, or if rs1 < rs2, etc. https://riscv.org/specifications/isa-spec-pdf/ https://riscv.org/specifications/isa-spec-pdf/ Take a look at the "RV32/64G Instruction Set Listings" table to get a feel for the encodings.
- waterhouse 6y agoAlso, to the specific "0b1100011 in the lowest bits" question, page 8 of the spec shows that, for an instruction to be 32 bits, the lowest two bits must be 11 (non-11 is used for 16-bit) and the next three bits must not all be 111 (111 is used for 48-bit and larger instructions).
- phkahler 6y agoI spent some time defining an alternate encoding of the base instruction set. I dont think they did a good job, but it's also not easy to do better. I started from an assumption of variable length - 16 bit or 32 bit opcodes plus immediate data in 16 bit chunks. It's not easy. Remember all those strange bit positions are irrelevant in hardware. But they are a bitch for things like linkers.
- zozbot234 6y agoIt has to encode 32 GPR's and three-operand instructions so instruction encoding is a bit cramped, even in 32 bits. 16-bit encodings are reserved for "compressed" special-case forms of existing 32-bit instructions.
- phkahler 6y agoRight, so I made 16bit opcodes only have 4 bits for register indexes. 32bit ones would provide the 5th bit for each register. That means a compiler should prefer the first 16 registers in order to reduce code size, but they are all still available. It also meant a reduced size chip with half the registers would not need different instruction encodings. Compressed was an afterthought on Risc-V. A well thought out afterthought, but you do things differently when you know in advance.
- zozbot234 6y agoCompressed was very explicitly made optional so that implementers would have the choice of recycling that encoding space for something else. It was not just an "afterthought".
- delfinom 6y ago>Remember all those strange bit positions are irrelevant in hardware. What, they are absolutely relevant in hardware and selected to optimize the resulting generated hardware.
- phkahler 6y ago
- _chris_ 6y agoBeing "simple" for a C program to decode is not the point; generating the smallest hardware to decode instructions and to reduce the critical path for things like deducing the instruction operands are. For example, the operands all stay in the same position, which prevents putting decode on the critical path before you can figure out which registers you need to read (which is doubly important for superscalar designs which need to compute the register dependence graph). Likewise, the sign-extend bit for immediates is always in the same place, providing relief for another potential critical path.
- kingosticks 6y agoExactly this. We had a hardware design where the difference between a load and store was a single bit, we also had a register file that wasn't afraid of bit flips, and part of the decode was on the critical path so it wasn't sufficiently parity protected. You can imagine what happened and how fun that was to debug.
- deleted 6y ago[deleted]
- fluffything 6y ago> Is there any published rationale for the RISC-V instruction encoding? Computer Organization and Design, RISC-V edition, goes into these. R-types have opcode = 0b0110011, SB (branch) types have opcode = 0b1100011, etc. The lower bits also have extra meanings (16 bit, 48 bit, etc. instruction). This allows hardware to just branch on these bits in sub-groups. The hardware pipeline for 16 bit is different than that of 48 bit, and the 48-bit is probably even optional.
- ur-whale 6y agoThe ISA was likely designed for efficient implementation in Silicon rather than being easy to grok by a human. To see what I mean, have a gander at this: https://github.com/ulx3s/apple2fpga/blob/master/cpu6502.vhd https://github.com/ulx3s/apple2fpga/blob/master/cpu6502.vhd