zoukankan      html  css  js  c++  java
  • 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))
                      )
                      );
    

     

  • 相关阅读:
    线程锁lock&rlock
    threading.local
    threading Event
    python中的eval 和 exec 和 execfile
    cloud-init 常见问题
    systemd
    cloud-init 的命令行
    原生js实现Promise
    js 指定位置插入html标签(可编辑div)
    js 实现复制粘贴文本过滤(保留文字和图片)
  • 原文地址:https://www.cnblogs.com/mikewolf2002/p/11302879.html
Copyright © 2011-2022 走看看