皋陶 发表于 2021-3-6 15:18:27

E203 译码模块(2)

本帖最后由 皋陶 于 2021-3-6 15:24 编辑

E203 译码模块(1)E203 译码模块(2)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 == 6'b000000);
   wire rv32_srli   = rv32_op_imm & rv32_func3_101 & (rv32_instr == 6'b000000);
   wire rv32_srai   = rv32_op_imm & rv32_func3_101 & (rv32_instr == 6'b010000);

//对一些移位指令,shamt must be zero for RV32I,在RV64I中才可以不为0

wire rv32_sxxi_shamt_legl = (rv32_instr == 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));
   // 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;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 == 5'b00010);
   wire rv32_sc_w      = rv32_amo & rv32_func3_010 & (rv32_func7 == 5'b00011);
   wire rv32_amoswap_w = rv32_amo & rv32_func3_010 & (rv32_func7 == 5'b00001);
   wire rv32_amoadd_w= rv32_amo & rv32_func3_010 & (rv32_func7 == 5'b00000);
   wire rv32_amoxor_w= rv32_amo & rv32_func3_010 & (rv32_func7 == 5'b00100);
   wire rv32_amoand_w= rv32_amo & rv32_func3_010 & (rv32_func7 == 5'b01100);
   wire rv32_amoor_w   = rv32_amo & rv32_func3_010 & (rv32_func7 == 5'b01000);
   wire rv32_amomin_w= rv32_amo & rv32_func3_010 & (rv32_func7 == 5'b10000);
   wire rv32_amomax_w= rv32_amo & rv32_func3_010 & (rv32_func7 == 5'b10100);
   wire rv32_amominu_w = rv32_amo & rv32_func3_010 & (rv32_func7 == 5'b11000);
   wire rv32_amomaxu_w = rv32_amo & rv32_func3_010 & (rv32_func7 == 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 lsu_info_size= rv32 ? rv32_func3 : 2'b10;
   // The RV16 always is signed
   wire       lsu_info_usign = rv32? rv32_func3 : 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 == 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 == 2'b11);

wire rv16_all0s_ilgl= rv16_func3_000 //rv16_func3= rv32_instr;
                         & rv32_func3_000 //rv32_func3= rv32_instr;
                         & rv32_rd_x0   //rv32_rd   = rv32_instr;
                         & opcode_6_5_00
                         & opcode_4_2_000
                         & (opcode == 2'b00);

wire rv16_all1s_ilgl= rv16_func3_111
                         & rv32_func3_111
                         & rv32_rd_x31
                         & opcode_6_5_11
                         & opcode_4_2_111
                         & (opcode == 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))
                  )
                  );完


页: [1]
查看完整版本: E203 译码模块(2)