有人预言,RISC-V或将是继Intel和Arm之后的第三大主流处理器体系。欢迎访问全球首家只专注于RISC-V单片机行业应用的中文网站
您需要 登录 才可以下载或查看,没有帐号?立即注册
x
本帖最后由 皋陶 于 2021-3-6 15:24 编辑
E203 译码模块(3)
常用的alu算术运算指令(包括ecall和 ebreak)在regular alu单元处理。regular alu单元为alu单元的一个子单元。regular单元的信息总线共21位,格式如下图所示,其中grp为000:
下面的代码产生regular alu单元的信息总线。
- // ALU Instructions
- wire rv32_addi = rv32_op_imm & rv32_func3_000;
- wire rv32_slti = rv32_op_imm & rv32_func3_010;
- wire rv32_sltiu = rv32_op_imm & rv32_func3_011;
- wire rv32_xori = rv32_op_imm & rv32_func3_100;
- wire rv32_ori = rv32_op_imm & rv32_func3_110;
- wire rv32_andi = rv32_op_imm & rv32_func3_111;
- wire rv32_slli = rv32_op_imm & rv32_func3_001 & (rv32_instr[31:26] == 6'b000000);
- wire rv32_srli = rv32_op_imm & rv32_func3_101 & (rv32_instr[31:26] == 6'b000000);
- wire rv32_srai = rv32_op_imm & rv32_func3_101 & (rv32_instr[31:26] == 6'b010000);
- //对一些移位指令,shamt[5] must be zero for RV32I,在RV64I中才可以不为0
- wire rv32_sxxi_shamt_legl = (rv32_instr[25] == 1'b0);
- wire rv32_sxxi_shamt_ilgl = (rv32_slli | rv32_srli | rv32_srai) & (~rv32_sxxi_shamt_legl);
- wire rv32_add = rv32_op & rv32_func3_000 & rv32_func7_0000000;
- wire rv32_sub = rv32_op & rv32_func3_000 & rv32_func7_0100000;
- wire rv32_sll = rv32_op & rv32_func3_001 & rv32_func7_0000000;
- wire rv32_slt = rv32_op & rv32_func3_010 & rv32_func7_0000000;
- wire rv32_sltu = rv32_op & rv32_func3_011 & rv32_func7_0000000;
- wire rv32_xor = rv32_op & rv32_func3_100 & rv32_func7_0000000;
- wire rv32_srl = rv32_op & rv32_func3_101 & rv32_func7_0000000;
- wire rv32_sra = rv32_op & rv32_func3_101 & rv32_func7_0100000;
- wire rv32_or = rv32_op & rv32_func3_110 & rv32_func7_0000000;
- wire rv32_and = rv32_op & rv32_func3_111 & rv32_func7_0000000;
- //对rv32 nop指令,31-20位为0
- wire rv32_nop = rv32_addi & rv32_rs1_x0 & rv32_rd_x0 & (~(|rv32_instr[31:20]));
- // The ALU group of instructions will be handled by 1cycle ALU-datapath
- wire ecall_ebreak = rv32_ecall | rv32_ebreak | rv16_ebreak;
- //当前指令是alu_op指令
- wire alu_op = (~rv32_sxxi_shamt_ilgl) & (~rv16_sxxi_shamt_ilgl)
- & (~rv16_li_lui_ilgl) & (~rv16_addi4spn_ilgl) & (~rv16_addi16sp_ilgl) &
- ( rv32_op_imm
- | rv32_op & (~rv32_func7_0000001) // Exclude the MULDIV
- | rv32_auipc
- | rv32_lui
- | rv16_addi4spn
- | rv16_addi
- | rv16_lui_addi16sp
- | rv16_li | rv16_mv
- | rv16_slli
- | rv16_miscalu
- | rv16_add
- | rv16_nop | rv32_nop
- | rv32_wfi // We just put WFI into ALU and do nothing in ALU
- | ecall_ebreak)
- ;
- wire need_imm;
- wire [`E203_DECINFO_ALU_WIDTH-1:0] alu_info_bus;
- assign alu_info_bus[`E203_DECINFO_GRP ] = `E203_DECINFO_GRP_ALU;
- assign alu_info_bus[`E203_DECINFO_RV32 ] = rv32;
- assign alu_info_bus[`E203_DECINFO_ALU_ADD] = rv32_add | rv32_addi | rv32_auipc |
- rv16_addi4spn | rv16_addi | rv16_addi16sp | rv16_add |
- // We also decode LI and MV as the add instruction, becuase
- // they all add x0 with a RS2 or Immeidate, and then write into RD
- rv16_li | rv16_mv;
- assign alu_info_bus[`E203_DECINFO_ALU_SUB] = rv32_sub | rv16_sub;
- assign alu_info_bus[`E203_DECINFO_ALU_SLT] = rv32_slt | rv32_slti;
- assign alu_info_bus[`E203_DECINFO_ALU_SLTU] = rv32_sltu | rv32_sltiu;
- assign alu_info_bus[`E203_DECINFO_ALU_XOR] = rv32_xor | rv32_xori | rv16_xor;
- assign alu_info_bus[`E203_DECINFO_ALU_SLL] = rv32_sll | rv32_slli | rv16_slli;
- assign alu_info_bus[`E203_DECINFO_ALU_SRL] = rv32_srl | rv32_srli | rv16_srli;
- assign alu_info_bus[`E203_DECINFO_ALU_SRA] = rv32_sra | rv32_srai | rv16_srai;
- assign alu_info_bus[`E203_DECINFO_ALU_OR ] = rv32_or | rv32_ori | rv16_or;
- assign alu_info_bus[`E203_DECINFO_ALU_AND] = rv32_and | rv32_andi | rv16_andi | rv16_and;
- assign alu_info_bus[`E203_DECINFO_ALU_LUI] = rv32_lui | rv16_lui;
- assign alu_info_bus[`E203_DECINFO_ALU_OP2IMM] = need_imm;
- assign alu_info_bus[`E203_DECINFO_ALU_OP1PC ] = rv32_auipc;
- assign alu_info_bus[`E203_DECINFO_ALU_NOP ] = rv16_nop | rv32_nop;
- assign alu_info_bus[`E203_DECINFO_ALU_ECAL ] = rv32_ecall;
- assign alu_info_bus[`E203_DECINFO_ALU_EBRK ] = rv32_ebreak | rv16_ebreak;
- assign alu_info_bus[`E203_DECINFO_ALU_WFI ] = rv32_wfi;
复制代码
alu中包含一个csr读写控制子单元,所有csr指令都在这个子单元中执行。下面csr读写控制单元的信息总线,其中grp为011
- wire csr_op = rv32_csr;
- wire [`E203_DECINFO_CSR_WIDTH-1:0] csr_info_bus;
- assign csr_info_bus[`E203_DECINFO_GRP ] = `E203_DECINFO_GRP_CSR;
- assign csr_info_bus[`E203_DECINFO_RV32 ] = rv32;
- assign csr_info_bus[`E203_DECINFO_CSR_CSRRW ] = rv32_csrrw | rv32_csrrwi;
- assign csr_info_bus[`E203_DECINFO_CSR_CSRRS ] = rv32_csrrs | rv32_csrrsi;
- assign csr_info_bus[`E203_DECINFO_CSR_CSRRC ] = rv32_csrrc | rv32_csrrci;
- assign csr_info_bus[`E203_DECINFO_CSR_RS1IMM] = rv32_csrrwi | rv32_csrrsi | rv32_csrrci;
- assign csr_info_bus[`E203_DECINFO_CSR_ZIMMM ] = rv32_rs1;
- assign csr_info_bus[`E203_DECINFO_CSR_RS1IS0] = rv32_rs1_x0;
- assign csr_info_bus[`E203_DECINFO_CSR_CSRIDX] = rv32_instr[31:20];
复制代码 alu中乘法除法子单元进行乘法,除法运算,该单元的信息总线格式为:
- // MUL/DIV Instructions
- wire rv32_mul = rv32_op & rv32_func3_000 & rv32_func7_0000001;
- wire rv32_mulh = rv32_op & rv32_func3_001 & rv32_func7_0000001;
- wire rv32_mulhsu = rv32_op & rv32_func3_010 & rv32_func7_0000001;
- wire rv32_mulhu = rv32_op & rv32_func3_011 & rv32_func7_0000001;
- wire rv32_div = rv32_op & rv32_func3_100 & rv32_func7_0000001;
- wire rv32_divu = rv32_op & rv32_func3_101 & rv32_func7_0000001;
- wire rv32_rem = rv32_op & rv32_func3_110 & rv32_func7_0000001;
- wire rv32_remu = rv32_op & rv32_func3_111 & rv32_func7_0000001;
- // The MULDIV group of instructions will be handled by MUL-DIV-datapath
- `ifdef E203_SUPPORT_MULDIV//{
- wire muldiv_op = rv32_op & rv32_func7_0000001;
- `endif//}
- `ifndef E203_SUPPORT_MULDIV//{
- wire muldiv_op = 1'b0;
- `endif//}
- wire [`E203_DECINFO_MULDIV_WIDTH-1:0] muldiv_info_bus;
- assign muldiv_info_bus[`E203_DECINFO_GRP ] = `E203_DECINFO_GRP_MULDIV;
- assign muldiv_info_bus[`E203_DECINFO_RV32 ] = rv32 ;
- assign muldiv_info_bus[`E203_DECINFO_MULDIV_MUL ] = rv32_mul ;
- assign muldiv_info_bus[`E203_DECINFO_MULDIV_MULH ] = rv32_mulh ;
- assign muldiv_info_bus[`E203_DECINFO_MULDIV_MULHSU] = rv32_mulhsu ;
- assign muldiv_info_bus[`E203_DECINFO_MULDIV_MULHU ] = rv32_mulhu ;
- assign muldiv_info_bus[`E203_DECINFO_MULDIV_DIV ] = rv32_div ;
- assign muldiv_info_bus[`E203_DECINFO_MULDIV_DIVU ] = rv32_divu ;
- assign muldiv_info_bus[`E203_DECINFO_MULDIV_REM ] = rv32_rem ;
- assign muldiv_info_bus[`E203_DECINFO_MULDIV_REMU ] = rv32_remu ;
- assign muldiv_info_bus[`E203_DECINFO_MULDIV_B2B ] = i_muldiv_b2b;
- assign dec_mulhsu = rv32_mulh | rv32_mulhsu | rv32_mulhu;
- assign dec_mul = rv32_mul;
- assign dec_div = rv32_div ;
- assign dec_divu = rv32_divu;
- assign dec_rem = rv32_rem;
- assign dec_remu = rv32_remu;
复制代码alu中的AGU子单元,主要负责Load,store指令和A扩展指令的地址生成,以及A扩展指令的微操作拆分和执行。 传输到AGU模块的信息总线格式为: - // ===========================================================================
- // Load/Store Instructions
- wire rv32_lb = rv32_load & rv32_func3_000;
- wire rv32_lh = rv32_load & rv32_func3_001;
- wire rv32_lw = rv32_load & rv32_func3_010;
- wire rv32_lbu = rv32_load & rv32_func3_100;
- wire rv32_lhu = rv32_load & rv32_func3_101;
- wire rv32_sb = rv32_store & rv32_func3_000;
- wire rv32_sh = rv32_store & rv32_func3_001;
- wire rv32_sw = rv32_store & rv32_func3_010;
- // ===========================================================================
- // Atomic Instructions
- `ifdef E203_SUPPORT_AMO//{
- wire rv32_lr_w = rv32_amo & rv32_func3_010 & (rv32_func7[6:2] == 5'b00010);
- wire rv32_sc_w = rv32_amo & rv32_func3_010 & (rv32_func7[6:2] == 5'b00011);
- wire rv32_amoswap_w = rv32_amo & rv32_func3_010 & (rv32_func7[6:2] == 5'b00001);
- wire rv32_amoadd_w = rv32_amo & rv32_func3_010 & (rv32_func7[6:2] == 5'b00000);
- wire rv32_amoxor_w = rv32_amo & rv32_func3_010 & (rv32_func7[6:2] == 5'b00100);
- wire rv32_amoand_w = rv32_amo & rv32_func3_010 & (rv32_func7[6:2] == 5'b01100);
- wire rv32_amoor_w = rv32_amo & rv32_func3_010 & (rv32_func7[6:2] == 5'b01000);
- wire rv32_amomin_w = rv32_amo & rv32_func3_010 & (rv32_func7[6:2] == 5'b10000);
- wire rv32_amomax_w = rv32_amo & rv32_func3_010 & (rv32_func7[6:2] == 5'b10100);
- wire rv32_amominu_w = rv32_amo & rv32_func3_010 & (rv32_func7[6:2] == 5'b11000);
- wire rv32_amomaxu_w = rv32_amo & rv32_func3_010 & (rv32_func7[6:2] == 5'b11100);
- `endif//E203_SUPPORT_AMO}
- `ifndef E203_SUPPORT_AMO//{
- wire rv32_lr_w = 1'b0;
- wire rv32_sc_w = 1'b0;
- wire rv32_amoswap_w = 1'b0;
- wire rv32_amoadd_w = 1'b0;
- wire rv32_amoxor_w = 1'b0;
- wire rv32_amoand_w = 1'b0;
- wire rv32_amoor_w = 1'b0;
- wire rv32_amomin_w = 1'b0;
- wire rv32_amomax_w = 1'b0;
- wire rv32_amominu_w = 1'b0;
- wire rv32_amomaxu_w = 1'b0;
- `endif//}
- wire amoldst_op = rv32_amo | rv32_load | rv32_store | rv16_lw | rv16_sw | (rv16_lwsp & (~rv16_lwsp_ilgl)) | rv16_swsp;
- // The RV16 always is word
- wire [1:0] lsu_info_size = rv32 ? rv32_func3[1:0] : 2'b10;
- // The RV16 always is signed
- wire lsu_info_usign = rv32? rv32_func3[2] : 1'b0;
- wire [`E203_DECINFO_AGU_WIDTH-1:0] agu_info_bus;
- assign agu_info_bus[`E203_DECINFO_GRP ] = `E203_DECINFO_GRP_AGU;
- assign agu_info_bus[`E203_DECINFO_RV32 ] = rv32;
- assign agu_info_bus[`E203_DECINFO_AGU_LOAD ] = rv32_load | rv32_lr_w | rv16_lw | rv16_lwsp;
- assign agu_info_bus[`E203_DECINFO_AGU_STORE ] = rv32_store | rv32_sc_w | rv16_sw | rv16_swsp;
- assign agu_info_bus[`E203_DECINFO_AGU_SIZE ] = lsu_info_size;
- assign agu_info_bus[`E203_DECINFO_AGU_USIGN ] = lsu_info_usign;
- assign agu_info_bus[`E203_DECINFO_AGU_EXCL ] = rv32_lr_w | rv32_sc_w;
- assign agu_info_bus[`E203_DECINFO_AGU_AMO ] = rv32_amo & (~(rv32_lr_w | rv32_sc_w));// We seperated the EXCL out of AMO in LSU handling
- assign agu_info_bus[`E203_DECINFO_AGU_AMOSWAP] = rv32_amoswap_w;
- assign agu_info_bus[`E203_DECINFO_AGU_AMOADD ] = rv32_amoadd_w ;
- assign agu_info_bus[`E203_DECINFO_AGU_AMOAND ] = rv32_amoand_w ;
- assign agu_info_bus[`E203_DECINFO_AGU_AMOOR ] = rv32_amoor_w ;
- assign agu_info_bus[`E203_DECINFO_AGU_AMOXOR ] = rv32_amoxor_w ;
- assign agu_info_bus[`E203_DECINFO_AGU_AMOMAX ] = rv32_amomax_w ;
- assign agu_info_bus[`E203_DECINFO_AGU_AMOMIN ] = rv32_amomin_w ;
- assign agu_info_bus[`E203_DECINFO_AGU_AMOMAXU] = rv32_amomaxu_w;
- assign agu_info_bus[`E203_DECINFO_AGU_AMOMINU] = rv32_amominu_w;
- assign agu_info_bus[`E203_DECINFO_AGU_OP2IMM ] = need_imm;
复制代码指令全为0和全为1是非法的指令,下面的代码判定指令是否为全0和全1。 - // Reuse the common signals as much as possible to save gatecounts
- wire rv32_all0s_ilgl = rv32_func7_0000000
- & rv32_rs2_x0
- & rv32_rs1_x0
- & rv32_func3_000
- & rv32_rd_x0
- & opcode_6_5_00
- & opcode_4_2_000
- & (opcode[1:0] == 2'b00);
- wire rv32_all1s_ilgl = rv32_func7_1111111
- & rv32_rs2_x31
- & rv32_rs1_x31
- & rv32_func3_111
- & rv32_rd_x31
- & opcode_6_5_11
- & opcode_4_2_111
- & (opcode[1:0] == 2'b11);
- wire rv16_all0s_ilgl = rv16_func3_000 //rv16_func3 = rv32_instr[15:13];
- & rv32_func3_000 //rv32_func3 = rv32_instr[14:12];
- & rv32_rd_x0 //rv32_rd = rv32_instr[11:7];
- & opcode_6_5_00
- & opcode_4_2_000
- & (opcode[1:0] == 2'b00);
- wire rv16_all1s_ilgl = rv16_func3_111
- & rv32_func3_111
- & rv32_rd_x31
- & opcode_6_5_11
- & opcode_4_2_111
- & (opcode[1:0] == 2'b11);
- wire rv_all0s1s_ilgl = rv32 ? (rv32_all0s_ilgl | rv32_all1s_ilgl)
- : (rv16_all0s_ilgl | rv16_all1s_ilgl);
复制代码以下的代码判断指令是否需要寄存器操作数1,寄存器操作数2,是否需要写目的寄存器。 - // All the RV32IMA need RD register except the
- // * Branch, Store,
- // * fence, fence_i
- // * ecall, ebreak
- wire rv32_need_rd =
- (~rv32_rd_x0) & (
- (
- (~rv32_branch) & (~rv32_store)
- & (~rv32_fence_fencei)
- & (~rv32_ecall_ebreak_ret_wfi)
- )
- );
- // All the RV32IMA need RS1 register except the
- // * lui
- // * auipc
- // * jal
- // * fence, fence_i
- // * ecall, ebreak
- // * csrrwi
- // * csrrsi
- // * csrrci
- wire rv32_need_rs1 =
- (~rv32_rs1_x0) & (
- (
- (~rv32_lui)
- & (~rv32_auipc)
- & (~rv32_jal)
- & (~rv32_fence_fencei)
- & (~rv32_ecall_ebreak_ret_wfi)
- & (~rv32_csrrwi)
- & (~rv32_csrrsi)
- & (~rv32_csrrci)
- )
- );
- // Following RV32IMA instructions need RS2 register
- // * branch
- // * store
- // * rv32_op
- // * rv32_amo except the rv32_lr_w
- wire rv32_need_rs2 = (~rv32_rs2_x0) & (
- (
- (rv32_branch)
- | (rv32_store)
- | (rv32_op)
- | (rv32_amo & (~rv32_lr_w))
- )
- );
复制代码 完
|