E203 译码模块(2)

       常用的alu算术运算指令(包括ecall和 ebreak)在regular alu单元处理。regular alu单元为alu单元的一个子单元。regular单元的信息总线共21位,格式如下图所示,其中grp为000:

       image


      下面的代码产生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

image


   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中乘法除法子单元进行乘法,除法运算,该单元的信息总线格式为:

image

  // 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模块的信息总线格式为:

 image
 

   // ===========================================================================
   // 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))
                  )
                  );

 

posted on 2019-08-05 14:38  迈克老狼2012  阅读(1105)  评论(0编辑  收藏  举报

导航