From 630c98e2a672b071dd8836648e044bcdbd692c77 Mon Sep 17 00:00:00 2001 From: Howard Su Date: Tue, 27 Aug 2019 19:53:02 -0700 Subject: [PATCH] Add RV32C support also fix the illegal instruction handling to raise the exception during execute stage. --- sim/iverilog/Makefile | 1 + sim/verilator/Makefile | 1 + .../source/PulseRain_RV2T_core.v | 34 ++- .../source/RV2T_compressed_decode.v | 234 ++++++++++++++++++ .../source/RV2T_execution_unit.v | 21 +- .../source/RV2T_instruction_decode.v | 38 ++- 6 files changed, 308 insertions(+), 21 deletions(-) create mode 100644 submodules/PulseRain_MCU/PulseRain_processor_core/source/RV2T_compressed_decode.v diff --git a/sim/iverilog/Makefile b/sim/iverilog/Makefile index 56ab449..b790e13 100644 --- a/sim/iverilog/Makefile +++ b/sim/iverilog/Makefile @@ -41,6 +41,7 @@ src_sub = \ ../PulseRain_processor_core/source/RV2T_execution_unit \ ../PulseRain_processor_core/source/RV2T_fetch_instruction \ ../PulseRain_processor_core/source/RV2T_instruction_decode \ +../PulseRain_processor_core/source/RV2T_compressed_decode \ ../PulseRain_processor_core/source/RV2T_machine_timer \ ../PulseRain_processor_core/source/RV2T_memory \ ../PulseRain_processor_core/source/RV2T_mm_reg \ diff --git a/sim/verilator/Makefile b/sim/verilator/Makefile index b77e6aa..6602785 100644 --- a/sim/verilator/Makefile +++ b/sim/verilator/Makefile @@ -39,6 +39,7 @@ src_sub = \ ../PulseRain_processor_core/source/RV2T_CSR \ ../PulseRain_processor_core/source/RV2T_fetch_instruction \ ../PulseRain_processor_core/source/RV2T_instruction_decode \ +../PulseRain_processor_core/source/RV2T_compressed_decode \ ../PulseRain_processor_core/source/RV2T_execution_unit \ ../PulseRain_processor_core/source/RV2T_data_access \ ../PulseRain_processor_core/source/RV2T_controller \ diff --git a/submodules/PulseRain_MCU/PulseRain_processor_core/source/PulseRain_RV2T_core.v b/submodules/PulseRain_MCU/PulseRain_processor_core/source/PulseRain_RV2T_core.v index d18b1ed..b910af2 100644 --- a/submodules/PulseRain_MCU/PulseRain_processor_core/source/PulseRain_RV2T_core.v +++ b/submodules/PulseRain_MCU/PulseRain_processor_core/source/PulseRain_RV2T_core.v @@ -103,7 +103,11 @@ module PulseRain_RV2T_core ( wire fetch_enable_out; wire [`XLEN - 1 : 0] fetch_IR_out; wire [`PC_BITWIDTH - 1 : 0] fetch_PC_out; - + + wire [`XLEN - 1 : 2] uncompress_IR_out; + wire uncompress_is_compressed; + wire uncompress_illegal_instr; + wire fetch_read_mem_enable; wire [`PC_BITWIDTH - 1 : 0] fetch_read_mem_addr; @@ -114,7 +118,8 @@ module PulseRain_RV2T_core ( wire [`XLEN - 1 : 2] decode_IR_out ; wire [`PC_BITWIDTH - 1 : 0] decode_PC_out ; - + wire decode_is_compress; + wire [`CSR_BITS - 1 : 0] decode_csr; wire decode_csr_enable; @@ -196,6 +201,7 @@ module PulseRain_RV2T_core ( wire decode_exception_illegal_instruction; wire csr_exception_illegal_instruction; + wire exception_illegal_instruction; wire activate_exception; wire [`EXCEPTION_CODE_BITS - 1 : 0] exception_code; @@ -375,6 +381,16 @@ module PulseRain_RV2T_core ( .read_mem_enable (fetch_read_mem_enable), .read_mem_addr (fetch_read_mem_addr)); + //--------------------------------------------------------------------- + // compressed instruction decode + //--------------------------------------------------------------------- + RV2T_compressed_decode RV2T_compressed_decode_i ( + .instr_i (fetch_IR_out), + .instr_o (uncompress_IR_out), + .is_compressed_o (uncompress_is_compressed), + .illegal_instr_o (uncompress_illegal_instr) + ); + //--------------------------------------------------------------------- // instruction decode //--------------------------------------------------------------------- @@ -386,8 +402,10 @@ module PulseRain_RV2T_core ( .decode_enable (decode_enable), .enable_in (fetch_enable_out), - .IR_in (fetch_IR_out), + .IR_in (uncompress_IR_out), .PC_in (fetch_PC_out), + .is_compressed_in (uncompress_is_compressed), + .exception_illegal_instr_in (uncompress_illegal_instr), .rs1 (rs1), .rs2 (rs2), @@ -419,7 +437,8 @@ module PulseRain_RV2T_core ( .ctl_MRET (decode_ctl_MRET), .ctl_WFI (decode_ctl_WFI), - .exception_illegal_instruction (decode_exception_illegal_instruction)); + .exception_illegal_instruction (decode_exception_illegal_instruction), + .is_compressed_out (decode_is_compress)); //--------------------------------------------------------------------- // execution unit @@ -452,11 +471,13 @@ module PulseRain_RV2T_core ( .ctl_MISC_MEM (decode_ctl_MISC_MEM), .ctl_MRET (decode_ctl_MRET), .ctl_MUL_DIV_FUNCT3 (decode_ctl_MUL_DIV_FUNCT3), - + .ctl_exception_illegal_instruction (decode_exception_illegal_instruction), + .rs1_in (reg_file_read_rs1_data_out), .rs2_in (reg_file_read_rs2_data_out), .csr_in (csr_read_data_out), + .is_compressed (decode_is_compress), .enable_out (), .rd_addr_out (exe_rd_addr_out), @@ -483,6 +504,7 @@ module PulseRain_RV2T_core ( .csr_addr_out (exe_csr_addr), .ecall_active (exception_ecall), .ebreak_active (exception_ebreak), + .exception_illegal_instruction (exception_illegal_instruction), .mret_active (mret_active), .mul_div_active (mul_div_active), .mul_div_done (mul_div_done) @@ -602,7 +624,7 @@ module PulseRain_RV2T_core ( .activate_exception (activate_exception), .exception_PC (exception_PC), .exception_addr (exception_addr), - .exception_illegal_instruction (decode_exception_illegal_instruction | csr_exception_illegal_instruction), + .exception_illegal_instruction (exception_illegal_instruction | csr_exception_illegal_instruction), .paused (paused) ); diff --git a/submodules/PulseRain_MCU/PulseRain_processor_core/source/RV2T_compressed_decode.v b/submodules/PulseRain_MCU/PulseRain_processor_core/source/RV2T_compressed_decode.v new file mode 100644 index 0000000..dc0a038 --- /dev/null +++ b/submodules/PulseRain_MCU/PulseRain_processor_core/source/RV2T_compressed_decode.v @@ -0,0 +1,234 @@ +`include "RV2T_common.vh" + +`default_nettype none + +module RV2T_compressed_decode +( + input wire [31:0] instr_i, + output reg [31:2] instr_o, + output wire is_compressed_o, + output reg illegal_instr_o +); + + always @(*) begin + illegal_instr_o = 1'b0; + instr_o = 30'b0; + + case (instr_i[1:0]) + // C0 + 2'b00: begin + case (instr_i[15:13]) + 3'b000: begin + // c.addi4spn -> addi rd', x2, imm + instr_o = {2'b0, instr_i[10:7], instr_i[12:11], instr_i[5], instr_i[6], 2'b00, 5'h02, 3'b000, 2'b01, instr_i[4:2], `CMD_OP_IMM}; + if (instr_i[12:5] == 8'b0) illegal_instr_o = 1'b1; + end + + 3'b001: begin + // c.fld -> fld rd', imm(rs1') + illegal_instr_o = 1'b1; + end + + 3'b010: begin + // c.lw -> lw rd', imm(rs1') + instr_o = {5'b0, instr_i[5], instr_i[12:10], instr_i[6], 2'b00, 2'b01, instr_i[9:7], 3'b010, 2'b01, instr_i[4:2], `CMD_LOAD}; + end + + 3'b011: begin + // c.flw -> flw rd', imm(rs1') + illegal_instr_o = 1'b1; + end + + 3'b101: begin + // c.fsd -> fsd rs2', imm(rs1') + illegal_instr_o = 1'b1; + end + + 3'b110: begin + // c.sw -> sw rs2', imm(rs1') + instr_o = {5'b0, instr_i[5], instr_i[12], 2'b01, instr_i[4:2], 2'b01, instr_i[9:7], 3'b010, instr_i[11:10], instr_i[6], 2'b00, `CMD_STORE}; + end + + 3'b111: begin + // c.fsw -> fsw rs2', imm(rs1') + illegal_instr_o = 1'b1; + end + default: begin + illegal_instr_o = 1'b1; + end + endcase + end + + + // C1 + 2'b01: begin + case (instr_i[15:13]) + 3'b000: begin + // c.addi -> addi rd, rd, nzimm + // c.nop + instr_o = {{6 {instr_i[12]}}, instr_i[12], instr_i[6:2], instr_i[11:7], 3'b0, instr_i[11:7], `CMD_OP_IMM}; + end + + 3'b001, 3'b101: begin + // 001: c.jal -> jal x1, imm + // 101: c.j -> jal x0, imm + instr_o = {instr_i[12], instr_i[8], instr_i[10:9], instr_i[6], instr_i[7], instr_i[2], instr_i[11], instr_i[5:3], {9 {instr_i[12]}}, 4'b0, ~instr_i[15], `CMD_JAL}; + end + + 3'b010: begin + // c.li -> addi rd, x0, nzimm + instr_o = {{6 {instr_i[12]}}, instr_i[12], instr_i[6:2], 5'b0, 3'b0, instr_i[11:7], `CMD_OP_IMM}; + if (instr_i[11:7] == 5'b0) illegal_instr_o = 1'b1; + end + + 3'b011: begin + // c.lui -> lui rd, imm + instr_o = {{15 {instr_i[12]}}, instr_i[6:2], instr_i[11:7], `CMD_LUI}; + + if (instr_i[11:7] == 5'h02) begin + // c.addi16sp -> addi x2, x2, nzimm + instr_o = {{3 {instr_i[12]}}, instr_i[4:3], instr_i[5], instr_i[2], instr_i[6], 4'b0, 5'h02, 3'b000, 5'h02, `CMD_OP_IMM}; + end else if (instr_i[11:7] == 5'b0) begin + illegal_instr_o = 1'b1; + end + + if ({instr_i[12], instr_i[6:2]} == 6'b0) illegal_instr_o = 1'b1; + end + + 3'b100: begin + case (instr_i[11:10]) + 2'b00, + 2'b01: begin + // 00: c.srli -> srli rd, rd, shamt + // 01: c.srai -> srai rd, rd, shamt + instr_o = {1'b0, instr_i[10], 5'b0, instr_i[6:2], 2'b01, instr_i[9:7], 3'b101, 2'b01, instr_i[9:7], `CMD_OP_IMM}; + if (instr_i[12] == 1'b1) illegal_instr_o = 1'b1; + if (instr_i[6:2] == 5'b0) illegal_instr_o = 1'b1; + end + + 2'b10: begin + // c.andi -> andi rd, rd, imm + instr_o = {{6 {instr_i[12]}}, instr_i[12], instr_i[6:2], 2'b01, instr_i[9:7], 3'b111, 2'b01, instr_i[9:7], `CMD_OP_IMM}; + end + + 2'b11: begin + case ({instr_i[12], instr_i[6:5]}) + 3'b000: begin + // c.sub -> sub rd', rd', rs2' + instr_o = {2'b01, 5'b0, 2'b01, instr_i[4:2], 2'b01, instr_i[9:7], 3'b000, 2'b01, instr_i[9:7], `CMD_OP}; + end + + 3'b001: begin + // c.xor -> xor rd', rd', rs2' + instr_o = {7'b0, 2'b01, instr_i[4:2], 2'b01, instr_i[9:7], 3'b100, 2'b01, instr_i[9:7], `CMD_OP}; + end + + 3'b010: begin + // c.or -> or rd', rd', rs2' + instr_o = {7'b0, 2'b01, instr_i[4:2], 2'b01, instr_i[9:7], 3'b110, 2'b01, instr_i[9:7], `CMD_OP}; + end + + 3'b011: begin + // c.and -> and rd', rd', rs2' + instr_o = {7'b0, 2'b01, instr_i[4:2], 2'b01, instr_i[9:7], 3'b111, 2'b01, instr_i[9:7], `CMD_OP}; + end + + 3'b100, + 3'b101, + 3'b110, + 3'b111: begin + // 100: c.subw + // 101: c.addw + illegal_instr_o = 1'b1; + end + endcase + end + endcase + end + + 3'b110, 3'b111: begin + // 0: c.beqz -> beq rs1', x0, imm + // 1: c.bnez -> bne rs1', x0, imm + instr_o = {{4 {instr_i[12]}}, instr_i[6:5], instr_i[2], 5'b0, 2'b01, instr_i[9:7], 2'b00, instr_i[13], instr_i[11:10], instr_i[4:3], instr_i[12], `CMD_BRANCH}; + end + endcase + end + + // C2 + 2'b10: begin + case (instr_i[15:13]) + 3'b000: begin + // c.slli -> slli rd, rd, shamt + instr_o = {7'b0, instr_i[6:2], instr_i[11:7], 3'b001, instr_i[11:7], `CMD_OP_IMM}; + if (instr_i[11:7] == 5'b0) illegal_instr_o = 1'b1; + if (instr_i[12] == 1'b1 || instr_i[6:2] == 5'b0) illegal_instr_o = 1'b1; + end + + 3'b001: begin + // c.fldsp -> fld rd, imm(x2) + illegal_instr_o = 1'b1; + end + + 3'b010: begin + // c.lwsp -> lw rd, imm(x2) + instr_o = {4'b0, instr_i[3:2], instr_i[12], instr_i[6:4], 2'b00, 5'h02, 3'b010, instr_i[11:7], `CMD_LOAD}; + if (instr_i[11:7] == 5'b0) illegal_instr_o = 1'b1; + end + + 3'b011: begin + // c.flwsp -> flw rd, imm(x2) + illegal_instr_o = 1'b1; + end + + 3'b100: begin + if (instr_i[12] == 1'b0) begin + // c.mv -> add rd/rs1, x0, rs2 + instr_o = {7'b0, instr_i[6:2], 5'b0, 3'b0, instr_i[11:7], `CMD_OP}; + + if (instr_i[6:2] == 5'b0) begin + // c.jr -> jalr x0, rd/rs1, 0 + instr_o = {12'b0, instr_i[11:7], 3'b0, 5'b0, `CMD_JALR}; + end + end else begin + // c.add -> add rd, rd, rs2 + instr_o = {7'b0, instr_i[6:2], instr_i[11:7], 3'b0, instr_i[11:7], `CMD_OP}; + + if (instr_i[11:7] == 5'b0) begin + // c.ebreak -> ebreak + instr_o = {30'h04_00_1C}; + if (instr_i[6:2] != 5'b0) + illegal_instr_o = 1'b1; + end else if (instr_i[6:2] == 5'b0) begin + // c.jalr -> jalr x1, rs1, 0 + instr_o = {12'b0, instr_i[11:7], 3'b000, 5'b00001, `CMD_JALR}; + end + end + end + + 3'b101: begin + // c.fsdsp -> fsd rs2, imm(x2) + illegal_instr_o = 1'b1; + end + + 3'b110: begin + // c.swsp -> sw rs2, imm(x2) + instr_o = {4'b0, instr_i[8:7], instr_i[12], instr_i[6:2], 5'h02, 3'b010, instr_i[11:9], 2'b00, `CMD_STORE}; + end + + 3'b111: begin + // c.fswsp -> fsw rs2, imm(x2) + illegal_instr_o = 1'b1; + end + endcase + end + + default: begin + // 32 bit (or more) instruction + instr_o = instr_i[31:2]; + end + endcase + end + + assign is_compressed_o = (instr_i[1:0] != 2'b11); + +endmodule \ No newline at end of file diff --git a/submodules/PulseRain_MCU/PulseRain_processor_core/source/RV2T_execution_unit.v b/submodules/PulseRain_MCU/PulseRain_processor_core/source/RV2T_execution_unit.v index fbbb1e6..3786a60 100644 --- a/submodules/PulseRain_MCU/PulseRain_processor_core/source/RV2T_execution_unit.v +++ b/submodules/PulseRain_MCU/PulseRain_processor_core/source/RV2T_execution_unit.v @@ -64,6 +64,8 @@ module RV2T_execution_unit ( input wire ctl_MUL_DIV_FUNCT3, + input wire is_compressed, + input wire ctl_exception_illegal_instruction, //===================================================================== // interface for the register file //===================================================================== @@ -105,9 +107,10 @@ module RV2T_execution_unit ( output reg [`CSR_BITS - 1 : 0] csr_addr_out, output reg ecall_active, output reg ebreak_active, + output reg exception_illegal_instruction, output reg mret_active, output wire mul_div_active, - output reg mul_div_done + output wire mul_div_done ); //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ @@ -175,6 +178,7 @@ module RV2T_execution_unit ( wire mul_div_enable; reg [31 : 0] mul_div_out_reg; + wire [31 : 0] Next_PC; //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // data path @@ -189,6 +193,8 @@ module RV2T_execution_unit ( assign J_immediate = {{12{IR_in[31]}},IR_in[19:12], IR_in[20], IR_in[30:25], IR_in[24:21], 1'b0}; assign shamt = Y [4 : 0]; + + assign Next_PC = is_compressed? PC_in + 2 : PC_in + 4; //--------------------------------------------------------------------- // funct3 //--------------------------------------------------------------------- @@ -204,6 +210,7 @@ module RV2T_execution_unit ( assign csr_uimm = IR_in [19 : 15]; assign csr_uimm_ext = {27'd0, csr_uimm}; + assign mul_div_done = (`ENABLE_HW_MUL_DIV) ? mul_div_enable_out : 1'b0; //--------------------------------------------------------------------- // X/Y register //--------------------------------------------------------------------- @@ -231,8 +238,6 @@ module RV2T_execution_unit ( exe_enable_d1 <= 0; - mul_div_done <= 0; - end else begin X <= rs1_in; @@ -242,9 +247,7 @@ module RV2T_execution_unit ( IR_out <= IR_in; exe_enable_d1 <= exe_enable; - - mul_div_done <= (`ENABLE_HW_MUL_DIV) ? mul_div_enable_out : 1'b0; - + if (exe_enable) begin reg_ctl_LUI <= ctl_LUI; @@ -259,6 +262,7 @@ module RV2T_execution_unit ( ecall_active <= ecall_active_i & ctl_SYSTEM; ebreak_active <= ebreak_active_i & ctl_SYSTEM; mret_active <= ctl_MRET & ctl_SYSTEM; + exception_illegal_instruction <= ctl_exception_illegal_instruction; end else begin @@ -273,6 +277,7 @@ module RV2T_execution_unit ( ecall_active <= 0; ebreak_active <= 0; mret_active <= 0; + exception_illegal_instruction <= 0; end end @@ -412,7 +417,7 @@ module RV2T_execution_unit ( end else if (exe_enable) begin jal_active <= ctl_JAL | ctl_MISC_MEM; if (ctl_MISC_MEM) begin - jal_addr <= PC_in + 4; + jal_addr <= Next_PC; end else begin jal_addr <= PC_in + J_immediate; end @@ -572,7 +577,7 @@ module RV2T_execution_unit ( end reg_ctl_JAL | reg_ctl_JALR : begin - data_out = PC_out + 4; + data_out = Next_PC; end mul_div_done : begin diff --git a/submodules/PulseRain_MCU/PulseRain_processor_core/source/RV2T_instruction_decode.v b/submodules/PulseRain_MCU/PulseRain_processor_core/source/RV2T_instruction_decode.v index 01241ee..47b53aa 100644 --- a/submodules/PulseRain_MCU/PulseRain_processor_core/source/RV2T_instruction_decode.v +++ b/submodules/PulseRain_MCU/PulseRain_processor_core/source/RV2T_instruction_decode.v @@ -39,8 +39,10 @@ module RV2T_instruction_decode ( // interface for the instruction fetch //===================================================================== input wire enable_in, - input wire [`XLEN - 1 : 0] IR_in, + input wire [`XLEN - 1 : 2] IR_in, input wire [`PC_BITWIDTH - 1 : 0] PC_in, + input wire is_compressed_in, + input wire exception_illegal_instr_in, //===================================================================== // interface for register read @@ -82,7 +84,8 @@ module RV2T_instruction_decode ( output reg ctl_MRET, output reg ctl_WFI, - output reg exception_illegal_instruction + output reg exception_illegal_instruction, + output reg is_compressed_out ); //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ @@ -95,7 +98,7 @@ module RV2T_instruction_decode ( wire [2 : 0] funct3; wire [11 : 0] funct12; reg illegal; - + //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // data path //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ @@ -116,14 +119,14 @@ module RV2T_instruction_decode ( // function fields //--------------------------------------------------------------------- - assign funct3 = IR_in [14 : 12]; - assign funct12 = IR_in [31 : 20]; + assign funct3 = IR_out [14 : 12]; + assign funct12 = IR_out [31 : 20]; //--------------------------------------------------------------------- // CSR read //--------------------------------------------------------------------- - assign csr = IR_in [31 : 20]; + assign csr = IR_out [31 : 20]; always @(*) begin : csr_read_enable_proc csr_read_enable = ctl_CSR; @@ -140,14 +143,16 @@ module RV2T_instruction_decode ( IR_out <= 0; PC_out <= 0; illegal <= 0; + is_compressed_out <= 0; end else begin IR_out <= IR_in[`XLEN - 1 : 2]; PC_out <= PC_in; + is_compressed_out <= is_compressed_in; if (|IR_in == 1'b0 || &IR_in == 1'b1) illegal <= 1'b1; else - illegal <= 1'b0; + illegal <= exception_illegal_instr_in; end end @@ -187,6 +192,14 @@ module RV2T_instruction_decode ( ctl_load_Y_from_imm_12 = 1'b1; ctl_save_to_rd = 1'b1; ctl_ALU_FUNCT3 = 1'b1; + + if (funct3 == `ALU_SLL && IR_out[31:25] != 7'b0) begin + exception_illegal_instruction = 1'b1; + end + + if (funct3 == `ALU_SRL_SRA && (IR_out[31] != 1'b0 || IR_out[29:25] != 5'b0 )) begin + exception_illegal_instruction = 1'b1; + end end `CMD_OP : begin @@ -195,6 +208,17 @@ module RV2T_instruction_decode ( ctl_save_to_rd = 1'b1; ctl_ALU_FUNCT3 = ~IR_out[25]; ctl_MUL_DIV_FUNCT3 = IR_out[25]; + + if (funct3 == `ALU_SRL_SRA || funct3 == `ALU_ADD_SUB) begin + if (IR_out[31] != 1'b0 || IR_out[29:26] != 4'b0 ) begin + exception_illegal_instruction = 1'b1; + end + end else begin + if (IR_out[31:26] != 6'b0) begin + exception_illegal_instruction = 1'b1; + end + end + end `CMD_LUI : begin