# RV32C support for srv32 > 宋唯廷, 劉孟璋 :::info The [RV32IM](#RV32IM), [RV32C](#RV32C), [SRV32](#SRV32) sections of this note serve as the theoretical notes. The implementation part of srv32c starts from the [Implementation](#Implementation) section. ::: [GitHub](https://github.com/timsong1/srv32) <br> # RV32IM ## Format ### `R-Type` ![image](https://hackmd.io/_uploads/rkFJ2hiwJl.png) | inst | length | |:------:|:-----------------:| | op | 7-bit **[0-6]** | | rd | 5-bit **[7-11]** | | funct3 | 3-bit **[12-14]** | | rs1 | 5-bit **[15-19]** | | rs2 | 5-bit **[20-24]** | | funct7 | 7-bit **[25-31]** | **instructions** - `SLT`, `SLTU`, `AND`, `OR`, `XOR`, `SLL`, `SRL`, `SRA`, `ADD`, `SUB`, `MUL`, `MULH`, `MULSU`, `MULU`, `DIV`, `DIVU`, `REM`, `REMU` > M-extension instructions expande to `R-Type` format <br> ### `I-Type` ![image](https://hackmd.io/_uploads/Syklb6ow1e.png) | inst | length | |:------:|:------------------:| | op | 7-bit **[0-6]** | | rd | 5-bit **[7-11]** | | funct3 | 3-bit **[12-14]** | | rs1 | 5-bit **[15-19]** | | imm | 12-bit **[20-31]** | **instructions** - `ADDI`, `SLTI`, `SLTIU`, `ANDI`, `ORI`, `XORI`, `SLLI`, `SLRI`, `SRAI`, `LW`, `LH`, `LHU`, `LB`, `LBU` <br> ### `S-Type` ![image](https://hackmd.io/_uploads/S1LCeaiPkg.png) | inst | length | |:------:|:-----------------:| | op | 7-bit **[0-6]** | | imm | 5-bit **[7-11]** | | funct3 | 3-bit **[12-14]** | | rs1 | 5-bit **[15-19]** | | rs2 | 5-bit **[20-24]** | | imm | 7-bit **[25-31]** | **instructions** - `SB`, `SH`, `SW` <br> ### `B-Type` ![image](https://hackmd.io/_uploads/B11ZpnoD1l.png) | inst | length | |:------:|:-----------------:| | op | 7-bit **[0-6]** | | imm | 1-bit **[7]** | | imm | 4-bit **[8-11]** | | funct3 | 3-bit **[12-14]** | | rs1 | 5-bit **[15-19]** | | rs2 | 5-bit **[20-24]** | | imm | 6-bit **[25-30]** | | imm | 1-bit **[31]** | **instructions** - `BEQ`, `BNE`, `BLT`, `BLTU`, `BGE`, `BGEU` <br> ### `U-Type` ![image](https://hackmd.io/_uploads/Hyp8OnsDke.png) | inst | length | |:----:|:------------------:| | op | 7-bit **[0-6]** | | rd | 5-bit **[7-11]** | | imm | 20-bit **[12-31]** | **instructions** - `LUI`, `AUIPC` <br> ### `J-Type` ![image](https://hackmd.io/_uploads/Skrs23sw1l.png) | inst | length | |:----:|:------------------:| | op | 7-bit **[0-6]** | | rd | 5-bit **[7-11]** | | imm | 8-bit **[12-19]** | | imm | 1-bit **[20]** | | imm | 10-bit **[21-30]** | | imm | 1-bit **[31]** | **instructions** - `JAL`, `JALR` <br> ### `NOP` ![image](https://hackmd.io/_uploads/HJ7-hhiPkg.png) **instructions** - `NOP` > `NOP` instruction is encoded as `ADDI x0, x0, 0` <br> ### `SYSTEM` ![image](https://hackmd.io/_uploads/r1el1wAv1e.png) **instructions** - `ECALL`, `EBREAK` <br> ## Decode <table> <thead> <tr> <th style="text-align: center">op</th> <th style="text-align: center">description</th> <th style="text-align: center">type</th> </tr> </thead> <tbody> <tr> <td>0110011</td> <td>arithmetic between <code>reg</code> and <code>reg</code></td> <td>R-Type</td> </tr> <tr> <td>0010011</td> <td>arithmetic between <code>reg</code> and <code>imm</code></td> <td rowspan="2">I-Type</td> </tr> <tr> <td>0010011</td> <td>load data</td> </tr> <tr> <td>0100011</td> <td>store data</td> <td rowspan>S-Type</td> </tr> <tr> <td>1100011</td> <td>conditional branch</td> <td rowspan>B-Type</td> </tr> <tr> <td>0010011</td> <td rowspan="2">upper <code>imm</code> arithmetic</td> <td rowspan="2">U-Type</td> </tr> <tr> <td>0110111</td> </tr> <tr> <td>1101111</td> <td rowspan="2">unconditional jump</td> <td rowspan="2">J-Type</td> </tr> <tr> <td>1100111</td> </tr> </tbody> </table> <br> # RV32C ## Introduction When certain 32-bit instructions have specific characteristics that allow them to be converted into compressed instructions: > 1. the immediate or address offset is small > 2. one of the registers is the zero register (x0), the ABI link register (`x1`), or the ABI stack pointer (`x2`) > 3. the **<font color="red">destination register</font>** and the **<font color="red">first source register</font>** are identical > 4. the registers used are **<font color="red">the 8 most popular ones</font>** (`x8` - `x15`). This is also the reason why some register fields in the C extension instructions are only **<font color="red">3 bits long</font>** RVC is designed such that each compressed instruction maps directly to a single 32-bit instruction in the base ISA (e.g., RV32I/E, RV64I, RV128I) or the F/D extensions. This design offers two key benefits: 1. **Simplified Hardware**: Hardware can expand RVC instructions during decoding, minimizing changes to existing microarchitectures and simplifying verification. 2. **Compiler Flexibility**: Compilers do not need to be aware of RVC; compression can be handled by the assembler and linker. However, compression-aware compilers can produce better results. The C extension integrates seamlessly with other standard extensions (e.g., M, A, F) without restricting functionality or reducing architectural flexibility. The C extension is not a standalone ISA and must be used alongside a base ISA. ![image](https://hackmd.io/_uploads/SybEceQw1e.png) <br> ## Format ### `CR-Type` **Instructions for arithmetic operations between registers** ![image](https://hackmd.io/_uploads/SJkvYJQwyg.png) | inst | length | |:------:|:-----------------:| | op | 2-bit **[0-1]** | | rs2 | 5-bit **[2-6]** | | rs1/rd | 5-bit **[7-11]** | | funct4 | 4-bit **[12-15]** | **instructions** - `C.JR`, `C.JALR`, `C.MV`, `C.ADD` <br> ### `CI-Type` **Instructions for arithmetic operations between immediate value and register** ![image](https://hackmd.io/_uploads/B1atnyQvye.png) | inst | length | |:------:|:-----------------:| | op | 2-bit **[0-1]** | | imm | 5-bit **[2-6]** | | rs1/rd | 5-bit **[7-11]** | | imm | 1-bit **[12]** | | funct3 | 3-bit **[13-15]** | **instructions** - `C.LWSP`, `C.LDSP`, `C.LQSP`, `C.FLWSP`, `C.FLDSP`, `C.LI`, `C.LUI`, `C.ADDI`, `C.ADDIW`, `C.ADDI16SP`, `C.SLLI` <br> ### `CSS-Type` **Instructions for stack-pointer-based stores** ![image](https://hackmd.io/_uploads/rybG0k7Pyg.png) | inst | length | |:------:|:-----------------:| | op | 2-bit **[0-1]** | | rs2 | 5-bit **[2-6]** | | imm | 1-bit **[7-12]** | | funct3 | 3-bit **[13-15]** | **instructions** - `C.SWSP`, `C.SDSP`, `C.SQSP`, `C.FSWSP`, `C.FSDSP` <br> ### `CIW-Type` **Instructions for stack-pointer-based loads** ![image](https://hackmd.io/_uploads/rytpGxmvke.png) | inst | length | |:------:|:-----------------:| | op | 2-bit **[0-1]** | | rd' | 3-bit **[2-4]** | | imm | 8-bit **[5-12]** | | funct3 | 3-bit **[13-15]** | **instructions** - `C.ADDI4SPN` <br> ### `CL-Type` **Instructions for register-based loads** ![image](https://hackmd.io/_uploads/rys-ygQDye.png) | inst | length | |:------:|:-----------------:| | op | 2-bit **[0-1]** | | rd' | 3-bit **[2-4]** | | imm | 2-bit **[5-6]** | | rs1' | 3-bit **[7-9]** | | imm | 2-bit **[10-12]** | | funct3 | 3-bit **[13-15]** | **instructions** - `C.LW`, `C.LD`, `C.LQ`, `C.FLW`, `C.FLD` <br> ### `CS-Type` **Instructions for register-based stores** ![image](https://hackmd.io/_uploads/SyjjleQv1e.png) | inst | length | |:------:|:-----------------:| | op | 2-bit **[0-1]** | | rs2' | 3-bit **[2-4]** | | imm | 2-bit **[5-6]** | | rs1' | 3-bit **[7-9]** | | imm | 3-bit **[10-12]** | | funct3 | 3-bit **[13-15]** | **instructions** - `C.SW`, `C.SD`, `C.SQ`, `C.FSW`, `C.FSD` <br> ### `CA-Type` **Instructions for atomic operations between immediate value and register** ![image](https://hackmd.io/_uploads/HkppNeXwJx.png) | inst | length | |:--------:|:-----------------:| | op | 2-bit **[0-1]** | | rs2' | 3-bit **[2-4]** | | funct2 | 2-bit **[5-6]** | | rs1'/rd' | 3-bit **[7-9]** | | funct6 | 6-bit **[10-15]** | **instructions** - `C.AND`, `C.OR`, `C.XOR`, `C.SUB` <br> ### `CB-Type` **Instructions for conditional control transfers / register shift** ![image](https://hackmd.io/_uploads/ByRObe7Dkg.png) | inst | length | |:------:|:-----------------:| | op | 2-bit **[0-1]** | | imm | 5-bit **[2-6]** | | rs1' | 3-bit **[7-9]** | | imm | 3-bit **[10-12]** | | funct3 | 3-bit **[13-15]** | **instructions** - `C.BEQZ`, `C.BNEZ`, `C.SRLI`, `C.SRAI`, `C.ANDI` <br> ### `CJ-Type` **Instructions for unconditional control transfers** ![image](https://hackmd.io/_uploads/SkhG51Xvkg.png) | inst | length | |:------:|:-----------------:| | op | 2-bit **[0-1]** | | imm | 11-bit **[2-12]** | | funct3 | 3-bit **[13-15]** | **instructions** - `C.J`, `C.JAL` <br> ### `NOP` ![image](https://hackmd.io/_uploads/ByN5Blmwyx.png) **instructions** - `C.NOP` <br> ### `Breakpoint` ![image](https://hackmd.io/_uploads/ByeyIeXwJg.png) **instructions** - `C.EBREAK` <br> ### `Illegal` ![image](https://hackmd.io/_uploads/SJrXIxmv1l.png) <br> --- <br> ## Decode ### `Type Decode` The following is the decoding method for C-Extension instructions. <table style="text-align: center"> <thead> <tr> <th style="text-align:center">op</th> <th style="text-align:center">func3</th> <th style="text-align:center">type</th> </tr> </thead> <tbody> <tr> <td>10</td> <td>100</td> <td>CR-type</td> </tr> <tr> <td rowspan="3" style="border-right: 1px solid #52525b">01</td> <td>000</td> <td rowspan="5">CI-type</td> </tr> <tr> <td>010</td> </tr> <tr> <td>011</td> </tr> <tr> <td rowspan="2" style="border-right: 1px solid #52525b">10</td> <td>000</td> </tr> <tr> <td>010</td> </tr> <tr> <td>10</td> <td>110</td> <td>CSS-type</td> </tr> <tr> <td>00</td> <td>000</td> <td>CIW-type</td> </tr> <tr> <td>00</td> <td>010</td> <td>CL-type</td> </tr> <tr> <td>00</td> <td>110</td> <td>CS-type</td> </tr> <tr> <td style="color:red"><b>01</b></td> <td style="color:red"><b>100</b></td> <td>CA-type</td> </tr> <tr> <td rowspan="3" style="color:red;border-right: 1px solid #52525b"><b>01</b></td> <td style="color:red"><b>100</b></td> <td rowspan="3">CB-type</td> </tr> <tr> <td>110</td> </tr> <tr> <td>111</td> </tr> <tr> <td rowspan="2" style="border-right: 1px solid #52525b">01</td> <td>001</td> <td rowspan="2">CJ-type</td> </tr> <tr> <td>101</td> </tr> </tbody> </table> <br> It can be observed that most of the C-extension instructions can be directly decoded using the `op` and `func3`. However, when `op=01` and `func3=100`, two different instruction formats (CA-type and CB-type) can be decoded. <br> <table style="text-align: center"> <thead> <tr> <th style="text-align:center">op</th> <th style="text-align:center">func3</th> <th style="text-align:center">inst[11:10]</th> <th style="text-align:center">type</th> </tr> </thead> <tbody> <tr> <td rowspan="6" style="border-right: 1px solid #52525b">01</td> <td rowspan="4" style="border-right: 1px solid #52525b">100</td> <td>11</td> <td>CA-type</td> </tr> <tr> <td>00</td> <td rowspan="5">CB-type</td> </tr> <tr> <td>01</td> </tr> <tr> <td>10</td> </tr> <tr> <td>110</td> <td rowspan="2">-</td> </tr> <tr> <td>111</td> </tr> </tbody> </table> Therefore, in the case where `op=01` and `func3=100`, we will need an additional 2 bits `inst[11:10]` to assist in decoding. <br> ### `Register Decode` * `CR-Type`, `CI-Type`, and `CSS-Type` instructions can use any of the RV32I registers (`x0`-`x31`) > This means that the register field (`rs1` / `rs2` / `rd`) length of these three types of instructions is as same as normal instructions (**5-bit**). * `CIW-Type`, `CL-Type`, `CS-Type`, `CA-Type`, and `CB-Type` instructions are limited to just 8 of them (`x8`-`x15`) > This means that the register field (`rs1'` / `rs2'` / `rd'`) length of these five types is shorter than normal instructions (**<font color="red">3-bit</font>**) > The regisers are mapped to `x8` - `x15` <table> <thead> <tr> <th colspan=2>reg(3-bit)</th> <th colspan=2>mapped reg(5-bit)</th> </tr> </thead> <tbody> <tr> <td>x0</td> <td>000</td> <td>x8 ( <code>s0</code> )</td> <td>01000</td> </tr> <tr> <td>x1</td> <td>001</td> <td>x9 ( <code>s1</code> )</td> <td>01001</td> </tr> <tr> <td>x2</td> <td>010</td> <td>x10 ( <code>a0</code> )</td> <td>01010</td> </tr> <tr> <td>x3</td> <td>011</td> <td>x11 ( <code>a1</code> )</td> <td>01011</td> </tr> <tr> <td>x4</td> <td>100</td> <td>x12 ( <code>a2</code> )</td> <td>01100</td> </tr> <tr> <td>x5</td> <td>101</td> <td>x13 ( <code>a3</code> )</td> <td>01101</td> </tr> <tr> <td>x6</td> <td>110</td> <td>x14 ( <code>a4</code> )</td> <td>01110</td> </tr> <tr> <td>x7</td> <td>111</td> <td>x15 ( <code>a5</code> )</td> <td>01111</td> </tr> </tbody> </table> <br> ### `Expansion` Each C Extension instructions usually corresponds to a base instruction #### CR-type <table> <thead> <tr> <th width="100px" style="text-align:center">RV32C</th> <th width="100px" style="text-align:center">RV32I</th> <th style="text-align:center">Description</th> </tr> </thead> <tbody> <tr> <th>C.JALR</th> <th>JALR</th> <th>Perform an unconditional control transfer to the address in register <code>rs1</code> and write the address of the instruction following the jump (pc+2) to the link register.</th> </tr> <tr> <th>C.JR</th> <th>JALR</th> <th>Perform an unconditional control transfer to the address in register <code>rs1</code></th> </tr> <tr> <th>C.ADD</th> <th>ADD</th> <th>Add the values in registers <code>rd</code> and <code>rs2</code> and write the result to register <code>rd</code></th> </tr> <tr> <th>C.MV</th> <th>ADD</th> <th>Copy the value in register <code>rs2</code> into register <code>rd</code></th> </tr> </tbody> </table> * `C.JALR` expands to `jalr x0, 0(rs1)` * `C.JR` expands to `jalr x1, 0(rs1)` * `C.ADD` expands to `add rd, rd, rs2` * `C.MV` expands to `add rd, x0, rs2` <br> #### CI-type <table> <thead> <tr> <th width="125px" style="text-align:center">RV32C</th> <th width="125px" style="text-align:center">RV32I</th> <th style="text-align:center">Description</th> </tr> </thead> <tbody> <tr> <th>C.LUI</th> <th>LUI</th> <th>Load the non-zero 6-bit immediate field into bits 17–12 of the destination register, clear the bottom 12 bits, and sign-extend bit 17 into all higher bits of the destination</th> </tr> <tr> <th>C.LI</th> <th>ADDI</th> <th>Load the sign-extended 6-bit immediate, <code>imm</code>, into register <code>rd</code></th> </tr> <tr> <th>C.ADDI</th> <th>ADDI</th> <th>Add the non-zero sign-extended 6-bit immediate to the value in register <code>rd</code> then writes the result to <code>rd</code></th> </tr> <tr> <th>C.ADDI16SP</th> <th>ADDI</th> <th>Add the non-zero sign-extended 6-bit immediate to the value in the stack pointer (x2), usually be used to adjust the stack pointer in procedure prologues and epilogues</th> </tr> <tr> <th>C.SLLI</th> <th>SLLI</th> <th>Load the sign-extended 6-bit immediate, `imm`, into register <code>rd</code></th> </tr> <tr> <th>C.LWSP</th> <th>LW</th> <th>Loads a 32-bit value from memory into register <code>rd</code></th> </tr> </tbody> </table> * `C.LUI` expands to `lui rd, nzimm` * `C.LI` expands to `addi rd, x0, imm` * `C.ADDI` expands to `addi rd, rd, nzimm` * `C.ADDI16SP` expands to `addi x2, x2, nzimm` * `C.SLLI` expands to `slli rd, rd, shamt` * `C.LWSP` expands to `lw rd, offset(x2)` <br> > `C.ADDI` is valid when `rd!=x0` and `imm!=0`, > The code points with `rd=x0` encode the `C.NOP`, > The code points with `imm=0` encode the `C.HINT` <br> #### CSS-type <table> <thead> <tr> <th width="125px" style="text-align:center">RV32C</th> <th width="125px" style="text-align:center">RV32I</th> <th style="text-align:center">Description</th> </tr> </thead> <tbody> <tr> <th>C.SWSP</th> <th>SW</th> <th>Store a 32-bit value in register <code>rs2</code> to memory. It computes an effective address by adding the zero-extended offset, scaled by 4, to the stack pointer (x2)</th> </tr> </tbody> </table> * `C.SWSP` expands to `sw rs2, offset(x2)` <br> #### CIW-type <table> <thead> <tr> <th width="125px" style="text-align:center">RV32C</th> <th width="125px" style="text-align:center">RV32I</th> <th style="text-align:center">Description</th> </tr> </thead> <tbody> <tr> <th>C.ADDI4SPN</th> <th>ADDI</th> <th>Add a zero-extended non-zero immediate, scaled by 4, to the stack pointer (x2), and write the result to <code>rd '</code></th> </tr> </tbody> </table> * `C.ADDI4SPN` expands to `addi rd ', x2, nzuimm` <br> #### CL-type <table> <thead> <tr> <th width="125px" style="text-align:center">RV32C</th> <th width="125px" style="text-align:center">RV32I</th> <th style="text-align:center">Description</th> </tr> </thead> <tbody> <tr> <th>C.LW</th> <th>LW</th> <th>Load a 32-bit value from memory into register <code>rd '</code></th> </tr> </tbody> </table> * `C.LW` expands to `lw rd, offset(rs1')` <br> #### CS-type <table> <thead> <tr> <th width="125px" style="text-align:center">RV32C</th> <th width="125px" style="text-align:center">RV32I</th> <th style="text-align:center">Description</th> </tr> </thead> <tbody> <tr> <th>C.SW</th> <th>SW</th> <th>Store a 32-bit value in register <code>rs2 ′</code> to memory</th> </tr> </tbody> </table> * `C.SW` expands to `sw rs2, offset(rs1')` <br> #### CA-type <table> <thead> <tr> <th width="125px" style="text-align:center">RV32C</th> <th width="125px" style="text-align:center">RV32I</th> <th style="text-align:center">Description</th> </tr> </thead> <tbody> <tr> <th>C.SUB</th> <th>SUB</th> <th>Subtract the value in register <code>rs2 ′</code> from the value in register <code>rd ′</code>, then write the result to register <code>rd ′</code></th> </tr> <tr> <th>C.XOR</th> <th>XOR</th> <th>Compute the bitwise XOR of the values in registers <code>rd ′</code> and <code>rs2 ′</code>, then write the result to register <code>rd ′</code></th> </tr> <tr> <th>C.OR</th> <th>OR</th> <th>Compute the bitwise OR of the values in registers <code>rd ′</code> and <code>rs2 ′</code>, then write the result to register <code>rd ′</code></th> </tr> <tr> <th>C.AND</th> <th>AND</th> <th>Compute the bitwise AND of the values in registers <code>rd ′</code> and <code>rs2 ′</code>, then write the result to register <code>rd ′</code></th> </tr> </tbody> </table> * `C.SUB` expands to `sub rd', rd', rs2'` * `C.XOR` expands to `xor rd', rd', rs2'` * `C.OR` expands to `or rd', rd', rs2'` * `C.AND` expands to `and rd', rd', rs2'` <br> #### CB-type <table> <thead> <tr> <th width="125px" style="text-align:center">RV32C</th> <th width="125px" style="text-align:center">RV32I</th> <th style="text-align:center">Description</th> </tr> </thead> <tbody> <tr> <th>C.SRLI</th> <th>SRLI</th> <th>Perform a logical right shift of the value in register <code>rd ′</code> then write the result to <code>rd ′</code></th> </tr> <tr> <th>C.SRAI</th> <th>SRAI</th> <th>Perform a arithmetic right shift of the value in register <code>rd ′</code> then write the result to <code>rd ′</code></th> </tr> <tr> <th>C.ANDI</th> <th>ANDI</th> <th>Compute the bitwise AND of the value in register <code>rd ′</code> and the sign-extended 6-bit immediate, then write the result to <code>rd ′</code></th> </tr> <tr> <th>C.BEQZ</th> <th>BEQ</th> <th>Perform conditional control transfers, and take the branch if the value in register <code>rs1 ′</code> is zero</th> </tr> <tr> <th>C.BNEZ</th> <th>BNE</th> <th>Perform conditional control transfers, and take the branch if the value in register <code>rs1 ′</code> contains a nonzero value</th> </tr> </tbody> </table> * `C.SRLI` expands to `srli rd', rd', shamt` * `C.SRAI` expands to `srai rd', rd', shamt` * `C.ANDI` expands to `andi rd', rd', imm` * `C.BEQZ` expands to `beq rs1, x0, offset` * `C.BNEZ` expands to `bne rs1, x0, offset` <br> #### CJ-type <table> <thead> <tr> <th width="125px" style="text-align:center">RV32C</th> <th width="125px" style="text-align:center">RV32I</th> <th style="text-align:center">Description</th> </tr> </thead> <tbody> <tr> <th>C.JAL</th> <th>JAL</th> <th>Perform an unconditional control transfer</th> </tr> <tr> <th>C.J</th> <th>JAL</th> <th>Perform an unconditional control transfer and additionally write the address of the instruction following the jump (pc+2) to the link register (x1)</th> </tr> </tbody> </table> * `C.JAL` expands to `jal x1, offset` * `C.J` expands to `jal x0, offset` > <font color="red">**`C.JAL` is an RV32C-only instruction**</font> <br> ### Conclusion <table style="text-align: center"> <thead> <tr> <th style="text-align:center">op</th> <th style="text-align:center">func</th> <th style="text-align:center">inst[11:10]</th> <th style="text-align:center">type</th> <th style="text-align:center">reg len</th> </tr> </thead> <tbody> <tr> <td>10</td> <td>100</td> <td rowspan="10">-</td> <td>CR-type</td> <td rowspan="7">5-bit ( <code>x0</code>-<code>x31</code> )</td> </tr> <tr> <td rowspan="3" style="border-right: 1px solid #52525b">01</td> <td>000</td> <td rowspan="5">CI-type</td> </tr> <tr> <td>010</td> </tr> <tr> <td>011</td> </tr> <tr> <td rowspan="2" style="border-right: 1px solid #52525b">10</td> <td>000</td> </tr> <tr> <td>010</td> </tr> <tr> <td>10</td> <td>110</td> <td>CSS-type</td> </tr> <tr> <td>00</td> <td>000</td> <td>CIW-type</td> <td rowspan="9">3-bit ( <code>x8</code>-<code>x15</code> )</td> </tr> <tr> <td>00</td> <td>010</td> <td>CL-type</td> </tr> <tr> <td>00</td> <td>110</td> <td>CS-type</td> </tr> <tr> <td style="color:red"><b>01</b></td> <td style="color:red"><b>100</b></td> <td>11</td> <td>CA-type</td> </tr> <tr> <td rowspan="3" style="color:red;border-right: 1px solid #52525b"><b>01</b></td> <td style="color:red"><b>100</b></td> <td>00</td> <td rowspan="3">CB-type</td> </tr> <tr> <td>110</td> <td>01</td> </tr> <tr> <td>111</td> <td>10</td> </tr> <tr> <td rowspan="2" style="border-right: 1px solid #52525b">01</td> <td>001</td> <td rowspan="2">-</td> <td rowspan="2">CJ-type</td> </tr> <tr> <td>101</td> </tr> </tbody> </table> <br> # SRV32 ## Introduction srv32 is a simple RISC-V 3-stage pipeline processor and supports FreeRTOS ## Stages ### `stage 1 - IF/ID` #### instruction fetch * If reset signal is `True`, instruction will be `NOP` * If reset signal is `False` and stall signal is `False`, read instruction ```verilog= always @(posedge clk or negedge resetb) begin if (!resetb) begin ex_insn <= NOP; end else if (!if_stall) begin ex_insn <= inst; end end ``` <br> #### immediate decode & extend * set `imm` according to the instruction ```verilog= always @* begin case(inst[`OPCODE]) OP_AUIPC : imm = {inst[31:12], 12'd0}; // U-type OP_LUI : imm = {inst[31:12], 12'd0}; // U-type OP_JAL : imm = {{12{inst[31]}}, inst[19:12], inst[20], inst[30:21], 1'b0}; // J-type OP_JALR : imm = {{20{inst[31]}}, inst[31:20]}; // I-Type OP_BRANCH: imm = {{20{inst[31]}}, inst[7], inst[30:25], inst[11:8], 1'b0}; // B-type OP_LOAD : imm = {{20{inst[31]}}, inst[31:20]}; // I-type OP_STORE : imm = {{20{inst[31]}}, inst[31:25], inst[11:7]}; // S-type OP_ARITHI: imm = (inst[`FUNC3] == OP_SLL || inst[`FUNC3] == OP_SR) ? {27'h0, inst[24:20]} : {{20{inst[31]}}, inst[31:20]}; // I-type OP_ARITHR: imm = 'd0; // R-type OP_FENCE : imm = 'd0; OP_SYSTEM: imm = {20'h0, inst[31:20]}; default : imm = 'd0; endcase end ``` > Used instruction : `AUIPC`, `LUI`, `JAL`, `JALR`, `BEQ`, `BNE`, `BLTU`, `BGEU`, `AUIPC`, `AUIPC`, `AUIPC`, `AUIPC`, `AUIPC`, `AUIPC`, `AUIPC`, `AUIPC`, <br> #### Control Signal / Register setting ```verilog= always @(posedge clk or negedge resetb) begin if (!resetb) begin ex_imm <= 32'h0; ex_imm_sel <= 1'b0; ex_src1_sel <= 5'h0; ex_src2_sel <= 5'h0; ex_dst_sel <= 5'h0; ex_alu_op <= 3'h0; ex_subtype <= 1'b0; ex_memwr <= 1'b0; ex_alu <= 1'b0; ex_csr <= 1'b0; ex_csr_wr <= 1'b0; ex_lui <= 1'b0; ex_auipc <= 1'b0; ex_jal <= 1'b0; ex_jalr <= 1'b0; ex_branch <= 1'b0; ex_system <= 1'b0; ex_system_op <= 1'b0; ex_pc <= RESETVEC; ex_illegal <= 1'b0; ex_mul <= 1'b0; end else if (!if_stall) begin ex_imm <= imm; ex_imm_sel <= (inst[`OPCODE] == OP_JALR ) || (inst[`OPCODE] == OP_LOAD ) || (inst[`OPCODE] == OP_ARITHI); ex_src1_sel <= inst[`RS1]; ex_src2_sel <= inst[`RS2]; ex_dst_sel <= inst[`RD]; ex_alu_op <= inst[`FUNC3]; ex_subtype <= inst[`SUBTYPE] && !(inst[`OPCODE] == OP_ARITHI && inst[`FUNC3] == OP_ADD); ex_memwr <= inst[`OPCODE] == OP_STORE; ex_alu <= (inst[`OPCODE] == OP_ARITHI) || ((inst[`OPCODE] == OP_ARITHR) && (inst[`FUNC7] == 'h00 || inst[`FUNC7] == 'h20)); ex_csr <= (inst[`OPCODE] == OP_SYSTEM) && (inst[`FUNC3] != OP_ECALL); // CSRRS and CSRRC, if rs1==0, then the instruction // will not write to the CSR at all ex_csr_wr <= (inst[`OPCODE] == OP_SYSTEM) && (inst[`FUNC3] != OP_ECALL) && !(inst[`FUNC3] != OP_CSRRW && inst[`FUNC3] != OP_CSRRWI && inst[`RS1] == 5'h0); ex_lui <= inst[`OPCODE] == OP_LUI; ex_auipc <= inst[`OPCODE] == OP_AUIPC; ex_jal <= inst[`OPCODE] == OP_JAL; ex_jalr <= inst[`OPCODE] == OP_JALR; ex_branch <= inst[`OPCODE] == OP_BRANCH; ex_system <= (inst[`OPCODE] == OP_SYSTEM) && (inst[`FUNC3] == 3'b000); ex_system_op <= inst[`OPCODE] == OP_SYSTEM; ex_pc <= if_pc; ex_illegal <= !((inst[`OPCODE] == OP_AUIPC )|| (inst[`OPCODE] == OP_LUI )|| (inst[`OPCODE] == OP_JAL )|| (inst[`OPCODE] == OP_JALR )|| (inst[`OPCODE] == OP_BRANCH)|| ((inst[`OPCODE] == OP_LOAD ) && ((inst[`FUNC3] == OP_LB) || (inst[`FUNC3] == OP_LH) || (inst[`FUNC3] == OP_LW) || (inst[`FUNC3] == OP_LBU) || (inst[`FUNC3] == OP_LHU))) || ((inst[`OPCODE] == OP_STORE) && ((inst[`FUNC3] == OP_SB) || (inst[`FUNC3] == OP_SH) || (inst[`FUNC3] == OP_SW))) || (inst[`OPCODE] == OP_ARITHI)|| ((inst[`OPCODE] == OP_ARITHR) && (inst[`FUNC7] == 'h00 || inst[`FUNC7] == 'h20)) || ((inst[`OPCODE] == OP_ARITHR) && (inst[`FUNC7] == 'h01) && (RV32M == 1)) || (inst[`OPCODE] == OP_FENCE )|| (inst[`OPCODE] == OP_SYSTEM)); ex_mul <= (inst[`OPCODE] == OP_ARITHR) && (inst[`FUNC7] == 'h1) && (RV32M == 1); end end ``` <br> ### `stage 2 - EX` #### Branch Next PC Computation ```verilog= `define IF_NEXT_PC (4) always @* begin branch_taken = !ex_flush; next_pc = fetch_pc + `IF_NEXT_PC; ex_ill_branch = 1'b0; case(1'b1) ex_jal : next_pc = {result_jal[31: 1], 1'b0}; // setting the least-signicant bit of the result to zero ex_jalr : next_pc = {result_jalr[31: 1], 1'b0}; // setting the least-signicant bit of the result to zero ex_branch: begin case(ex_alu_op) OP_BEQ : begin next_pc = (result_subs[32: 0] == 'd0) ? ex_pc + ex_imm : fetch_pc + `IF_NEXT_PC; if (result_subs[32: 0] != 'd0) branch_taken = 1'b0; end OP_BNE : begin next_pc = (result_subs[32: 0] != 'd0) ? ex_pc + ex_imm : fetch_pc + `IF_NEXT_PC; if (result_subs[32: 0] == 'd0) branch_taken = 1'b0; end OP_BLT : begin next_pc = result_subs[32] ? ex_pc + ex_imm : fetch_pc + `IF_NEXT_PC; if (!result_subs[32]) branch_taken = 1'b0; end OP_BGE : begin next_pc = !result_subs[32] ? ex_pc + ex_imm : fetch_pc + `IF_NEXT_PC; if (result_subs[32]) branch_taken = 1'b0; end OP_BLTU: begin next_pc = result_subu[32] ? ex_pc + ex_imm : fetch_pc + `IF_NEXT_PC; if (!result_subu[32]) branch_taken = 1'b0; end OP_BGEU: begin next_pc = !result_subu[32] ? ex_pc + ex_imm : fetch_pc + `IF_NEXT_PC; if (result_subu[32]) branch_taken = 1'b0; end default: begin next_pc = fetch_pc; ex_ill_branch = 1'b1; end endcase end default : begin next_pc = fetch_pc + `IF_NEXT_PC; branch_taken = 1'b0; end endcase end ``` <br> #### Result Computation ```verilog= always @* begin case(1'b1) ex_memwr: ex_result = alu_op2; ex_jal: ex_result = ex_pc + `EX_NEXT_PC; ex_jalr: ex_result = ex_pc + `EX_NEXT_PC; ex_lui: ex_result = ex_imm; ex_auipc: ex_result = ex_pc + ex_imm; ex_csr: ex_result = ex_csr_read; ex_mul: case(ex_alu_op) OP_MUL : ex_result = result_mul [31: 0]; OP_MULH : ex_result = result_mul [63:32]; OP_MULSU : ex_result = result_mulsu[63:32]; OP_MULU : ex_result = result_mulu [63:32]; OP_DIV : ex_result = result_div [31: 0]; OP_DIVU : ex_result = result_divu [31: 0]; OP_REM : ex_result = result_rem [31: 0]; // OP_REMU default : ex_result = result_remu [31: 0]; endcase ex_alu: case(ex_alu_op) OP_ADD : if (ex_subtype == 1'b0) ex_result = alu_op1 + alu_op2; else ex_result = alu_op1 - alu_op2; // In RISC-V ISA spec, only shift amount // held in lower 5 bits of register OP_SLL : ex_result = alu_op1 << alu_op2[4:0]; OP_SLT : ex_result = result_subs[32] ? 'd1 : 'd0; OP_SLTU: ex_result = result_subu[32] ? 'd1 : 'd0; OP_XOR : ex_result = alu_op1 ^ alu_op2; OP_SR : if (ex_subtype == 1'b0) // notes: shift more than 32 is undefined ex_result = alu_op1 >>> alu_op2[4:0]; else ex_result = $signed(alu_op1) >>> alu_op2[4:0]; OP_OR : ex_result = alu_op1 | alu_op2; // OP_AND default: ex_result = alu_op1 & alu_op2; endcase default: begin ex_result = 32'h0; end endcase end ``` ### `stage 3 - WB` #### write back data ```verilog= always @* begin case(wb_alu_op) OP_LB : begin case(wb_raddr[1:0]) 2'b00: wb_rdata[31: 0] = {{24{dmem_rdata[7]}}, dmem_rdata[ 7: 0]}; 2'b01: wb_rdata[31: 0] = {{24{dmem_rdata[15]}}, dmem_rdata[15: 8]}; 2'b10: wb_rdata[31: 0] = {{24{dmem_rdata[23]}}, dmem_rdata[23:16]}; 2'b11: wb_rdata[31: 0] = {{24{dmem_rdata[31]}}, dmem_rdata[31:24]}; endcase end OP_LH : begin wb_rdata = (wb_raddr[1]) ? {{16{dmem_rdata[31]}}, dmem_rdata[31:16]} : {{16{dmem_rdata[15]}}, dmem_rdata[15: 0]}; end OP_LW : begin wb_rdata = dmem_rdata; end OP_LBU : begin case(wb_raddr[1:0]) 2'b00: wb_rdata[31: 0] = {24'h0, dmem_rdata[7:0]}; 2'b01: wb_rdata[31: 0] = {24'h0, dmem_rdata[15:8]}; 2'b10: wb_rdata[31: 0] = {24'h0, dmem_rdata[23:16]}; 2'b11: wb_rdata[31: 0] = {24'h0, dmem_rdata[31:24]}; endcase end OP_LHU : begin wb_rdata = (wb_raddr[1]) ? {16'h0, dmem_rdata[31:16]} : {16'h0, dmem_rdata[15: 0]}; end default: begin wb_rdata = 32'h0; end endcase end ``` <br> --- ## Control Signal ### 1. `ex_imm_sel` #### Assignment ```verilog= ex_imm_sel <= (inst[`OPCODE] == OP_JALR) || (inst[`OPCODE] == OP_LOAD) || (inst[`OPCODE] == OP_ARITHI); ``` * `ex_imm_sel=True`, when the instruction is ***I-type*** format * `ex_imm_sel=False`, when the instruction is other format #### Used Instruction: `JALR`, `LB`, `LH`, `LW`, `LBU`, `LHU`, `ADDI`, `SLTI`, `SLTIU`, `XORI`, `ORI`, `ANDI`, `SLLI`, `SRLI`, `SRAI` <br> ### 2. `ex_subtype` <br> ### 3. `ex_memwr` #### Assignment ```verilog= ex_memwr <= inst[`OPCODE] == OP_STORE; ``` * `ex_memwr <= True`, when the instruction is ***LOAD*** format * `ex_memwr <= False`, when the instruction is other format #### Used Instruction: `LB`, `LH`, `LW`, `LBU`, `LHU` <br> ### 4. `ex_alu` #### Assignment ```verilog= ex_alu <= (inst[`OPCODE] == OP_ARITHI) || ((inst[`OPCODE] == OP_ARITHR) && (inst[`FUNC7] == 'h00 || inst[`FUNC7] == 'h20)); ``` * `ex_alu <= True`, when the instruction is ***ARITH*** format * `ex_alu <= False`, when the instruction is other format #### Used Instruction: `ADDI`, `SLTI`, `SLTIU`, `XORI`, `ORI`, `ANDI`, `SLLI`, `SRLI`, `SRAI`, `ADD`, `SUB`, `SLT`, `SLTU`, `XOR`, `OR`, `AND`, `SRL`, `SRA`, `MUL`, `MULH`, `MULSU`, `MULU`, `DIV`, `DIVU`, `REM`, `REMU` <br> ### 5. `ex_lui` #### Assignment ```verilog= ex_lui <= inst[`OPCODE] == OP_LUI; ``` * `ex_lui <= True`, when the instruction is `LUI` * `ex_lui <= False`, when the instruction is other #### Used Instruction: `LUI` <br> ### 6. `ex_auipc` #### Assignment ```verilog= ex_auipc <= inst[`OPCODE] == OP_AUIPC; ``` * `ex_auipc <= True`, when the instruction is `AUIPC` * `ex_auipc <= False`, when the instruction is other #### Used Instruction: `AUIPC` <br> ### 7. `ex_jal` #### Assignment ```verilog= ex_jal <= inst[`OPCODE] == OP_JAL; ``` * `ex_jal <= True`, when the instruction is `JAL` * `ex_jal <= False`, when the instruction is other #### Used Instruction: `JAL` <br> ### 8. `ex_jalr` #### Assignment ```verilog= ex_jalr <= inst[`OPCODE] == OP_JALR; ``` * `ex_jalr <= True`, when the instruction is `JALR` * `ex_jalr <= False`, when the instruction is other #### Used Instruction: `JALR` <br> ### 9. `ex_branch` #### Assignment ```verilog= ex_branch <= inst[`OPCODE] == OP_BRANCH; ``` * `ex_branch <= True`, when the instruction is ***BRANCH*** format * `ex_branch <= False`, when the instruction is other #### Used Instruction: `BEQ`, `BNE`, `BLT`, `BGE`, `BLTU`, `BGEU` <br> ### 10. `ex_mul` #### Assignment ```verilog= ex_mul <= (inst[`OPCODE] == OP_ARITHR) && (inst[`FUNC7] == 'h1) && (RV32M == 1); ``` * `ex_mul <= True`, when the instruction is ***MULTIPLE*** * `ex_mul <= False`, when the instruction is other #### Used Instruction: `MUL`, `MULH`, `MULSU`, `MULU`, `DIV`, `DIVU`, `REM`, `REMU` <br> ### 11. `ex_system` #### Assignment ```verilog= ex_system <= (inst[`OPCODE] == OP_SYSTEM) &&(inst[`FUNC3] == 3'b000); ``` * `ex_system <= True`, when the instruction is `ECALL`, `EBREAK`, `MRET` * `ex_system <= False`, when the instruction is other #### Used Instruction: `ECALL`, `EBREAK`, `MRET` <br> ### 12. `ex_system_op` #### Assignment ```verilog= ex_system_op <= inst[`OPCODE] == OP_SYSTEM; ``` * `ex_system_op <= True`, when the instruction is ***SYSTEM*** format * `ex_system_op <= False`, when the instruction is other #### Used Instruction: `ECALL`, `EBREAK`, `MRET`, `CSSRW`, `CSSRS`, `CSSRC`, `CSSRWI`, `CSSRSI`, `CSSRCI` <br> ### 13. `ex_csr` #### Assignment ```verilog= ex_csr <= (inst[`OPCODE] == OP_SYSTEM) && (inst[`FUNC3] != OP_ECALL); ``` * `ex_csr <= True`, when the instruction is `CSSRW`, `CSSRS`, `CSSRC`, `CSSRWI`, `CSSRSI`, `CSSRCI` * `ex_csr <= False`, when the instruction is other #### Used Instruction: `CSSRW`, `CSSRS`, `CSSRC`, `CSSRWI`, `CSSRSI`, `CSSRCI` <br> ### 14. `ex_csr_wr` #### Assignment ```verilog= ex_csr_wr <= (inst[`OPCODE] == OP_SYSTEM) && (inst[`FUNC3] != OP_ECALL) && !(inst[`FUNC3] != OP_CSRRW && inst[`FUNC3] != OP_CSRRWI && inst[`RS1] == 5'h0); ``` * `ex_csr_wr <= True`, when the instruction is `CSRRW`, `CSRRWI`, `CSRRS`, `CSRRC` (Only when the value of `rs1` of `CSRRS`, `CSRRC` instruction is not equal to 0) * `ex_csr_wr <= False`, when the instruction is other #### Used Instruction: `CSSRW`, `CSSRS`, `CSSRC`, `CSSRWI` <br> ### Conclusion | | ex_imm_sel | ex_subtype | ex_memwr | ex_alu | ex_lui | ex_auipc | ex_jal | ex_jalr | ex_branch | ex_mul | ex_system | ex_system_op | ex_csr_wr | ex_csr | |:------ |:----------:|:----------:|:--------:|:------:|:------:|:--------:|:------:|:-------:|:---------:|:------:|:---------:|:------------:|:---------:|:------:| | LUI | ❌ | | ❌ | ❌ | ✔️ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | | AUIPC | ❌ | | ❌ | ❌ | ❌ | ✔️ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | | JAL | ❌ | | ❌ | ❌ | ❌ | ❌ | ✔️ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | | JALR | ✔️ | | ❌ | ❌ | ❌ | ❌ | ❌ | ✔️ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | | BEQ | ❌ | | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✔️ | ❌ | ❌ | ❌ | ❌ | ❌ | | BNE | ❌ | | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✔️ | ❌ | ❌ | ❌ | ❌ | ❌ | | BLT | ❌ | | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✔️ | ❌ | ❌ | ❌ | ❌ | ❌ | | BGE | ❌ | | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✔️ | ❌ | ❌ | ❌ | ❌ | ❌ | | BLTU | ❌ | | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✔️ | ❌ | ❌ | ❌ | ❌ | ❌ | | BGEU | ❌ | | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✔️ | ❌ | ❌ | ❌ | ❌ | ❌ | | LB | ✔️ | | ✔️ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | | LH | ✔️ | | ✔️ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | | LW | ✔️ | | ✔️ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | | LBU | ✔️ | | ✔️ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | | LHU | ✔️ | | ✔️ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | | SB | ❌ | | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | | SH | ❌ | | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | | SW | ❌ | | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | | ADDI | ✔️ | | ❌ | ✔️ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | | SLTI | ✔️ | | ❌ | ✔️ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | | SLTIU | ✔️ | | ❌ | ✔️ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | | XORI | ✔️ | | ❌ | ✔️ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | | ORI | ✔️ | | ❌ | ✔️ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | | ANDI | ✔️ | | ❌ | ✔️ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | | SLLI | ✔️ | | ❌ | ✔️ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | | SRAI | ✔️ | | ❌ | ✔️ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | | SRAI | ✔️ | | ❌ | ✔️ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | | ADD | ❌ | | ❌ | ✔️ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | | SUB | ❌ | | ❌ | ✔️ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | | SLL | ❌ | | ❌ | ✔️ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | | SLT | ❌ | | ❌ | ✔️ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | | SLTU | ❌ | | ❌ | ✔️ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | | XOR | ❌ | | ❌ | ✔️ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | | SRL | ❌ | | ❌ | ✔️ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | | SRA | ❌ | | ❌ | ✔️ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | | OR | ❌ | | ❌ | ✔️ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | | AND | ❌ | | ❌ | ✔️ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | | MUL | ❌ | | ❌ | ✔️ | ❌ | ❌ | ❌ | ❌ | ❌ | ✔️ | ❌ | ❌ | ❌ | ❌ | | MULH | ❌ | | ❌ | ✔️ | ❌ | ❌ | ❌ | ❌ | ❌ | ✔️ | ❌ | ❌ | ❌ | ❌ | | MULSU | ❌ | | ❌ | ✔️ | ❌ | ❌ | ❌ | ❌ | ❌ | ✔️ | ❌ | ❌ | ❌ | ❌ | | MULU | ❌ | | ❌ | ✔️ | ❌ | ❌ | ❌ | ❌ | ❌ | ✔️ | ❌ | ❌ | ❌ | ❌ | | DIV | ❌ | | ❌ | ✔️ | ❌ | ❌ | ❌ | ❌ | ❌ | ✔️ | ❌ | ❌ | ❌ | ❌ | | DIVU | ❌ | | ❌ | ✔️ | ❌ | ❌ | ❌ | ❌ | ❌ | ✔️ | ❌ | ❌ | ❌ | ❌ | | REM | ❌ | | ❌ | ✔️ | ❌ | ❌ | ❌ | ❌ | ❌ | ✔️ | ❌ | ❌ | ❌ | ❌ | | REMU | ❌ | | ❌ | ✔️ | ❌ | ❌ | ❌ | ❌ | ❌ | ✔️ | ❌ | ❌ | ❌ | ❌ | | ECALL | ❌ | | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✔️ | ✔️ | ❌ | ❌ | | EBREAK | ❌ | | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✔️ | ✔️ | ❌ | ❌ | | MERT | ❌ | | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✔️ | ✔️ | ❌ | ❌ | | CSRRW | ❌ | | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✔️ | ✔️ | ✔️ | | CSRRS | ❌ | | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✔️ | ✔️ | ✔️ | | CSRRC | ❌ | | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✔️ | ✔️ | ✔️ | | CSRRWI | ❌ | | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✔️ | ✔️ | ✔️ | | CSRRSI | ❌ | | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✔️ | ✔️ | ❌ | | CSRRCI | ❌ | | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✔️ | ✔️ | ❌ | --- <br> # Implementation ## Architecture ![image](https://hackmd.io/_uploads/HJ0VX61u1g.png) 1. Decode the instructions according to the opcode (`inst[1:0]`) * If op2 equals to `11`, then the instruction is base instruction * If op2 equals to `00`, `01`, or `10`, then the instruction is c-extension instruction > ex: > If instruction is `C.ADD`, then the instruction information ALU gains should be `ADD` 2. Execute instruction 3. Write back data <br> ## op & func3 Define ```verilog= // INST[1:0] = 2'b00 localparam [ 4: 0] OP_CADDI4SPN = 5'b00000, OP_CLW = 5'b01000, OP_CSW = 5'b11000; // INST[1:0] = 2'b01 localparam [ 4: 0] OP_CADDI = 5'b00001, OP_CJAL = 5'b00101, OP_CLI = 5'b01001, OP_CADDI16SP = 5'b01101, OP_CLUI = 5'b01101, OP_CSRLI = 5'b10001, OP_CSRAI = 5'b10001, OP_CANDI = 5'b10001, OP_CJ = 5'b10101, OP_CBEQZ = 5'b11001, OP_CBNEZ = 5'b11101; // INST[1:0] = 2'b01, no imm localparam [ 4: 0] OP_CSUB = 5'b10001, OP_CXOR = 5'b10001, OP_COR = 5'b10001, OP_CAND = 5'b10001; // INST[1:0] = 2'b10 localparam [ 4: 0] OP_CSLLI = 5'b00010, OP_CLWSP = 5'b01010, OP_CSWSP = 5'b11010; // INST[1:0] = 2'b10, no imm localparam [ 4: 0] OP_CJR = 5'b10010, OP_CMV = 5'b10010, OP_CJALR = 5'b10010, OP_CADD = 5'b10010, OP_CSYSTEM = 5'b10010; ``` > This part is for instruction define, the parameter `OP_XXX` is composed of `funct3` and `op2` ({inst[15:13]}) <br> ## Imm Decode This section is modified from [here](#immediate-decode-amp-extend). ``` diff= always @* begin case(inst[`OPCODE]) OP_AUIPC : imm = {inst[31:12], 12'd0}; // U-type OP_LUI : imm = {inst[31:12], 12'd0}; // U-type OP_JAL : imm = {{12{inst[31]}}, inst[19:12], inst[20], inst[30:21], 1'b0}; // J-type OP_JALR : imm = {{20{inst[31]}}, inst[31:20]}; // I-Type OP_BRANCH: imm = {{20{inst[31]}}, inst[7], inst[30:25], inst[11:8], 1'b0}; // B-type OP_LOAD : imm = {{20{inst[31]}}, inst[31:20]}; // I-type OP_STORE : imm = {{20{inst[31]}}, inst[31:25], inst[11:7]}; // S-type OP_ARITHI: imm = (inst[`FUNC3] == OP_SLL || inst[`FUNC3] == OP_SR) ? {27'h0, inst[24:20]} : {{20{inst[31]}}, inst[31:20]}; // I-type OP_ARITHR: imm = 'd0; // R-type OP_FENCE : imm = 'd0; OP_SYSTEM: imm = {20'h0, inst[31:20]}; default : imm = 'd0; endcase // case for C-Extenstion case({inst[`CFUNC3], inst[`COPCODE]}) // CI-type + OP_CLI : imm = {26'b0, inst[12], inst[6:2]}; + OP_CADDI : imm = {26'b0, inst[12], inst[6:2]}; + OP_CSLLI : imm = {26'b0, inst[12], inst[6:2]}; // C.LUI & C.ADDI16SP + OP_CLUI : imm = (inst[`C5RD]==5'd2) ? {22'b0, inst[12], inst[4:3], inst[5], inst[2], inst[6], 4'b0} : {14'b0, inst[12], inst[6:2], 12'b0}; + OP_CLWSP : imm = {24'b0, inst[3:2], inst[12], inst[6:4], 2'b0}; // CSS-type + OP_CSWSP : imm = {24'b0, inst[8:7], inst[12:9], 2'b0}; // CIW-type + OP_CADDI4SPN : imm = {22'b0, inst[10:7], inst[12:11], inst[5], inst[6], 2'b0}; // CL-type + OP_CLW : imm = {25'b0, inst[5], inst[12:10], inst[6], 2'b0}; // CS-type + OP_CSW : imm = {25'b0, inst[5], inst[12:10], inst[6], 2'b0}; // CB-type + OP_CBEQZ : imm = {23'b0, inst[12], inst[6:5], inst[2], inst[11:10], inst[4:3], 1'b0}; + OP_CBNEZ : imm = {23'b0, inst[12], inst[6:5], inst[2], inst[11:10], inst[4:3], 1'b0}; + OP_CSRLI : imm = (inst[11:10]==2'b0) ? {27'b0, inst[6:2]} : + (inst[11:10]==2'b1) ? {26'b0, inst[12], inst[6:2]} : + {26'b0, inst[12], inst[6:2]}; // CJ-type + OP_CJ : imm = {20'b0, inst[12], inst[8], inst[10:9], inst[7], inst[6], inst[2], inst[11], inst[4:2], 1'b0}; + OP_CJAL : imm = {20'b0, inst[12], inst[8], inst[10:9], inst[7], inst[6], inst[2], inst[11], inst[4:2], 1'b0}; + OP_CSYSTEM : imm = (inst[`C5RD] == 0 && inst[`C5RS2] == 0) ? 32'b1 : 32'b0; + default : imm = 'd0; endcase end ``` > The upper part is for base instructions, then the lower part is for c-extension instructions <br> ## Register This section is modified from [here](#Control-Signal--Register-setting) ``` diff= case(inst[`COPCODE]) + 2'b00: // CIW-type, CL-type, CS-type + begin + instc <= 1'b1; + ex_src1_sel <= {2'b1, inst[`C3RS1]}; + ex_src2_sel <= {2'b1, inst[`C3RS2]}; + ex_dst_sel <= {2'b1, inst[`C3RD]}; + end + 2'b01: + begin + case(inst[`CFUNC3]) + 3'b000, // CI-type + 3'b010, // CI-type + 3'b011: // CI-type + begin + instc <= 1'b1; + ex_src1_sel <= inst[`C5RS1]; + ex_src2_sel <= inst[`C5RS2]; + ex_dst_sel <= inst[`C5RD]; + end + 3'b001, // CJ-type + 3'b100, // CA-type, CB-type + 3'b101, // CJ-type + 3'b110, // CB-type + 3'b111: // CB-type + begin + instc <= 1'b1; + ex_src1_sel <= {2'b1, inst[`C3RS1]}; + ex_src2_sel <= {2'b1, inst[`C3RS2]}; + ex_dst_sel <= {2'b1, inst[`C3RD]}; + end + endcase + end + 2'b10: // CI-type, CSS-type + begin + instc <= 1'b1; + ex_src1_sel <= inst[`C5RS1]; + ex_src2_sel <= inst[`C5RS2]; + ex_dst_sel <= inst[`C5RD]; + end 2'b11: // base begin instc <= 1'b0; ex_src1_sel <= inst[`RS1]; ex_src2_sel <= inst[`RS2]; ex_dst_sel <= inst[`RD]; end endcase ``` > Because `CIW`, `CL`, `CS`, `CA`, `CB`, and `CJ` format instruction can use only part of the RV32I registers, we have to map the `rs1'`, `rs2'`, and `rd'` to the corresponded register. <br> ## ALU OP This section is modified from [here](#Control-Signal--Register-setting) ```diff= case(inst[`COPCODE]) 2'b11: ex_alu_op <= inst[`FUNC3]; default: begin // c-ext + case({inst[`CFUNC3], inst[`COPCODE]}) + OP_CLW: ex_alu_op <= OP_LW; + OP_CLWSP: ex_alu_op <= OP_LW; + OP_CSW: ex_alu_op <= OP_SW; + OP_CSWSP: ex_alu_op <= OP_SW; + OP_CBEQZ: ex_alu_op <= OP_BEQ; + OP_CBNEZ: ex_alu_op <= OP_BNE; + OP_CADD: ex_alu_op <= OP_ADD; + OP_COR: + begin + case(inst[6:5]) + 2'b00: ex_alu_op <= OP_ADD; + 2'b01: ex_alu_op <= OP_XOR; + 2'b10: ex_alu_op <= OP_OR; + 2'b11: ex_alu_op <= OP_AND; + endcase + end + default: ; endcase end endcase ``` > This part is for instruction expanding. > If the instruction is based instruction, then set the `ex_alu_op` with `funct3` > If the instruction is c-extension instruction, then decode the instruction with op2 and funct3, and set the `ex_alu_op` with corresponded `funct3` of based instruction. <br> ## Control Signal ### 1. `ex_imm_sel` This section is modified from [here](#1-ex_imm_sel). ```diff= ex_imm_sel <= (inst[`OPCODE] == OP_JALR ) || (inst[`OPCODE] == OP_LOAD ) || (inst[`OPCODE] == OP_ARITHI) || // c-ext + (({inst[`CFUNC3], inst[`COPCODE]} == OP_CJR) && (inst[12] == 1'b0) && (inst[`C5RS2] == 5'b0) && (inst[`C5RS1] != 5'b0)) || // C.JR + (({inst[`CFUNC3], inst[`COPCODE]} == OP_CJALR) && (inst[12] == 1'b1) && (inst[`C5RS2] == 5'b0) && (inst[`C5RS1] != 5'b0)) || // C.JALR + ({inst[`CFUNC3], inst[`COPCODE]} == OP_CLW) || // C.LW + ({inst[`CFUNC3], inst[`COPCODE]} == OP_CLWSP) || // C.LWSP + (({inst[`COPCODE], inst[`CFUNC3]} == OP_CADDI) && (inst[`C5RS1] != 5'b0)) || // C.ADDI + (({inst[`COPCODE], inst[`CFUNC3]} == OP_CLI) && (inst[`C5RS1] != 5'b0)) || // C.LI + (({inst[`COPCODE], inst[`CFUNC3]} == OP_CSLLI) && (inst[`C5RS1] != 5'b0)) || // C.SLLI + (({inst[`COPCODE], inst[`CFUNC3]} == OP_CSRLI) && (inst[`CFUNC2] == 2'b00)) || // C.SRLI + (({inst[`COPCODE], inst[`CFUNC3]} == OP_CSRAI) && (inst[`CFUNC2] == 2'b01)) || // C.SRAI + (({inst[`COPCODE], inst[`CFUNC3]} == OP_CANDI) && (inst[`CFUNC2] == 2'b10)); // C.SRAI ``` > Add additional conditions for c instructions - `C.JR`, `C.JALR`, `C.LW`, `C.LWSP`, `C.ADDI`, `C.LI`, `C.SLLI`, `C.SRLI`, `C.SRAI`, `C.ANDI` <br> ### 2. `ex_subtype` ### 3. `ex_memwr` This section is modified from [here](#3-ex_memwr) ```diff= ex_memwr <= (inst[`OPCODE] == OP_STORE) || // c-ext + ({inst[`CFUNC3], inst[`COPCODE]} == OP_CSW) || // C.SW + ({inst[`CFUNC3], inst[`COPCODE]} == OP_CSWSP); // C.SWSP ``` > Add additional instruction conditions for c instruction - `C.SW`, `CSWSP` <br> ### 4. `ex_alu` This section is modified from [here](#4-ex_alu) ```diff= ex_alu <= (inst[`OPCODE] == OP_ARITHI) || ((inst[`OPCODE] == OP_ARITHR) && (inst[`FUNC7] == 'h00 || inst[`FUNC7] == 'h20)) || // c-ext + (({inst[`COPCODE], inst[`CFUNC3]} == OP_CADD) && (inst[12]) && (inst[`CRD] != 5'b0) && (inst[`C5RS2] != 5'b0)) || // C.ADD + (({inst[`COPCODE], inst[`CFUNC3]} == OP_CMV) && (!inst[12]) && (inst[`CRD] != 5'b0) && (inst[`C5RS2] != 5'b0)) || // C.MV + (({inst[`COPCODE], inst[`CFUNC3]} == OP_CSUB) && (inst[`CFUNC6] == 6'b100011)) || // C.SUB, C.XOR, C.OR, C.AND + (({inst[`COPCODE], inst[`CFUNC3]} == OP_CADDI) && (inst[`C5RS1] != 5'b0)) || // C.ADDI + (({inst[`COPCODE], inst[`CFUNC3]} == OP_CLI) && (inst[`C5RS1] != 5'b0)) || // C.LI + (({inst[`COPCODE], inst[`CFUNC3]} == OP_CSLLI) && (inst[`C5RS1] != 5'b0)) || // C.SLLI + (({inst[`COPCODE], inst[`CFUNC3]} == OP_CSRLI) && (inst[`CFUNC2] == 2'b00)) || // C.SRLI + (({inst[`COPCODE], inst[`CFUNC3]} == OP_CSRAI) && (inst[`CFUNC2] == 2'b01)) || // C.SRAI + (({inst[`COPCODE], inst[`CFUNC3]} == OP_CANDI) && (inst[`CFUNC2] == 2'b10)); // C.ANDI ``` > Add additional conditions for c instructions - `C.ADD`, `C.MV`, `C.SUB`, `C.XOR`, `C.OR`, `C.AND`, `C.ADDI`, `C.LI`, `C.SLLI`, `C.SRLI`, `C.SRAI`, `C.ANDI` <br> ### 5. `ex_lui` This section is modified from [here](#5-ex_lui) ```diff= ex_lui <= (inst[`OPCODE] == OP_LUI) || // c-ext + (({inst[`CFUNC3], inst[`COPCODE]} == OP_CLUI) && (inst[`RD] != 5'd0) && (inst[`RD] != 5'd1) && (inst[`RD] != 5'd2)); // C.LUI ``` > Add additional conditions for c instruction - `C.LUI` <br> ### 6. `ex_jal` This section is modified from [here](#7-ex_jal) ```diff= ex_jal <= (inst[`OPCODE] == OP_JAL) || // c-ext + ({inst[`CFUNC3], inst[`COPCODE]} == OP_CJ) || // C.J + ({inst[`CFUNC3], inst[`COPCODE]} == OP_CJAL); // C.JAL ``` > Add additional conditions for c instructions - `C.J`, `C.JAL` <br> ### 7. `ex_jalr` This section is modified from [here](#8-ex_jalr) ```diff= ex_jalr <= (inst[`OPCODE] == OP_JALR) || // c-ext + (({inst[`CFUNC3], inst[`COPCODE]} == OP_CJR) && (!inst[12]) && (inst[`C5RS1] != 5'b0) && (inst[`C5RS2] == 5'b0)) || // C.JR + (({inst[`CFUNC3], inst[`COPCODE]} == OP_CJALR) && (inst[12]) && (inst[`C5RS1] != 5'b0) && (inst[`C5RS2] == 5'b0)) ; // C.JALR ``` > Add additional conditions for c instructions - `C.JR`, `C.JALR` <br> ### 8. `ex_branch` This section is modified from [here](#9-ex_branch) ```diff= ex_branch <= (inst[`OPCODE] == OP_BRANCH) || // c-ext + ({inst[`CFUNC3], inst[`COPCODE]} == OP_CBEQZ) || // C.BEQZ + ({inst[`CFUNC3], inst[`COPCODE]} == OP_CBNEZ); // C.BNEZ ``` > Add additional conditions for c instructions - `C.BEQZ`, `C.BNEZ` <br> ### 9. `ex_system` This section is modified from [here](#11-ex_system) ```diff= ex_system <= ((inst[`OPCODE] == OP_SYSTEM) && (inst[`FUNC3] == 3'b000)) || // c-ext + (({inst[`CFUNC3], inst[`COPCODE]} == OP_CSYSTEM) && (inst[12]) && (inst[`CRD] == 5'b0) && (inst[`C5RS2] == 5'b0)); ``` > Add additional instruction conditions for c instruction - `C.EBREAK` <br> ### 10. `ex_system_op` This section is modified from [here](#12-ex_system_op) ```diff= ex_system_op <= (inst[`OPCODE] == OP_SYSTEM) || // c-ext + (({inst[`CFUNC3], inst[`COPCODE]} == OP_CSYSTEM) && (inst[12]) && (inst[`CRD] == 5'b0) && (inst[`C5RS2] == 5'b0)); ``` > Add additional conditions for c instruction - `C.EBREAK` <br> ### 11. `ex_csr` This section is modified from [here](#13-ex_csr) ```diff= ex_csr <= ((inst[`OPCODE] == OP_SYSTEM) && (inst[`FUNC3] != OP_ECALL)) || // c-ext + (inst[`CINST] == 16'h9002); ``` > Add additional conditions for c instruction - `C.EBREAK` <br> ## PC ### Define ```diff= `define IF_NEXT_PC (4) `define EX_NEXT_PC (4) // c-ext pc +`define IF_NEXT_C_PC (2) +`define EX_NEXT_C_PC (2) ``` > Because the c extension instruction is 16-byte long, the program counter (`PC`) should increment by 2 by step instead of by 4 <br> ### Branch PC This section is modified from [here](#Branch-Next-PC-Computation) ```diff= always @* begin branch_taken = !ex_flush; + next_pc = (instc) ? (fetch_pc + `IF_NEXT_C_PC) : (fetch_pc + `IF_NEXT_PC); ex_ill_branch = 1'b0; case(1'b1) ex_jal : next_pc = {result_jal[31: 1], 1'b0}; // setting the least-signicant bit of the result to zero ex_jalr : next_pc = {result_jalr[31: 1], 1'b0}; // setting the least-signicant bit of the result to zero ex_branch: begin case(ex_alu_op) OP_BEQ : begin + next_pc = (result_subs[32: 0] == 'd0) ? + (ex_pc + ex_imm) : (instc) ? + (fetch_pc + `IF_NEXT_C_PC) : (fetch_pc + `IF_NEXT_PC); if (result_subs[32: 0] != 'd0) branch_taken = 1'b0; end OP_BNE : begin + next_pc = (result_subs[32: 0] != 'd0) ? + (ex_pc + ex_imm) : (instc) ? + (fetch_pc + `IF_NEXT_C_PC) : (fetch_pc + `IF_NEXT_PC); if (result_subs[32: 0] == 'd0) branch_taken = 1'b0; end OP_BLT : begin + next_pc = result_subs[32] ? + (ex_pc + ex_imm) : (instc) ? + (fetch_pc + `IF_NEXT_C_PC) : (fetch_pc + `IF_NEXT_PC); if (!result_subs[32]) branch_taken = 1'b0; end OP_BGE : begin + next_pc = !result_subs[32] ? + (ex_pc + ex_imm) : (instc) ? + (fetch_pc + `IF_NEXT_C_PC) : (fetch_pc + `IF_NEXT_PC); if (result_subs[32]) branch_taken = 1'b0; end OP_BLTU: begin + next_pc = result_subu[32] ? + (ex_pc + ex_imm) : (instc) ? + (fetch_pc + `IF_NEXT_C_PC) : (fetch_pc + `IF_NEXT_PC); if (!result_subu[32]) branch_taken = 1'b0; end OP_BGEU: begin + next_pc = !result_subu[32] ? + (ex_pc + ex_imm) : (instc) ? + (fetch_pc + `IF_NEXT_C_PC) : (fetch_pc + `IF_NEXT_PC); if (result_subu[32]) branch_taken = 1'b0; end default: begin + next_pc = fetch_pc; ex_ill_branch = 1'b1; end endcase end default : begin + next_pc = (instc) ? (fetch_pc + `IF_NEXT_C_PC) : (fetch_pc + `IF_NEXT_PC); branch_taken = 1'b0; end endcase end ``` > This part is for ***BRANCH*** instruction > Use a control signal (`instc`) to determine whether the PC should increment by 2 or 4 > * If `instc=0` (means base instruction), `PC` will increment by 4 > * If `instc=0` (means C extension instruction), `PC` will increment by 2 > The value of control signal `instc` is set at [here](#Register) <br> ### Jump PC This section is modified from [here](#Result-Computation) ```diff= always @* begin case(1'b1) ex_memwr: ex_result = alu_op2; + ex_jal: ex_result = (instc) ? (ex_pc + `EX_NEXT_C_PC) : (ex_pc + `EX_NEXT_PC); + ex_jalr: ex_result = (instc) ? (ex_pc + `EX_NEXT_C_PC) : (ex_pc + `EX_NEXT_PC); ex_lui: ex_result = ex_imm; ex_auipc: ex_result = ex_pc + ex_imm; ex_csr: ex_result = ex_csr_read; ex_mul: (...) // Remaining code is the same ``` > This part is for ***JUMP*** instruction > Use a control signal (`instc`) to determine whether the PC should increment by 2 or 4 > * If `instc=0` (means base instruction), `PC` will increment by 4 > * If `instc=0` (means C extension instruction), `PC` will increment by 2 > The value of control signal `instc` is set at [here](#Register) <br> # Test The origin structure is in `~/test/srv32` directory Our c-extension supported structure is in `~/repos/srv32` First, we test the original structure in RTL simulation Type `make all` in folder `srv32` ![image](https://hackmd.io/_uploads/SknUpfgdJe.png) Test out c-extension supported structure ![image](https://hackmd.io/_uploads/BJrACfg_ke.png) The error message show `Unsupport CSR register 0x0 at PC 0x00000010` Because the conversion of CSR instructions has not been successfully handled so far. ### Problem analysis 1. Some instructions might have been mistakenly identified as CSR instructions, resulting in illegal instructions. 2. Since the c-extension instructions related to CSR only include c.ebreak, there might have been an error during the decoding of this instruction. **We should be able to figure it out within a few days.** # Reference * https://hackmd.io/@kaeteyaruyo/risc-v-rvc#Instruction-Decompression * https://hackmd.io/@2gMSvG25RxKj2-N_rAY6zg/HkKaA_qUs?utm_source=preview-mode&utm_medium=rec * https://groups.google.com/a/groups.riscv.org/g/isa-dev/c/QJX63LeEux8?pli=1 * http://atp.ee.ncku.edu.tw/classview_58.html