执行概述
反压问题
指令译码
乱序发射队列
指令执行
主要就是把操作数根据操作类型送给ALU等运算单元
流水线冲突
WAR: 老东西要读A地,结果小东西先把老数据给覆盖了
WAW: 小东西先写了A地,结果小小东西还没用,老东西才刚完毕,又把A地写覆盖
RAW:小东西先读了A地,结果老东西还没把A地换新呢
WAW & WAR:可以通过寄存器重命名的方法将相关性去除;
RAW:
指令的交付
指令发射、派遣、执行、写回顺序
在一些比较高端的超标量处理器核中,流水线级数非常多,派遣和发射可能存在不同的含义。派遣往往表示指令经过译码之后被派发到不同的运算单元的等待队列中的过程。
而发射往往表示指令从运算单元的等待队列中(解决了数据依赖性之后)发射到运算单元开始执行的过程。
顺序发射、顺序执行、顺序写回
顺序发射、乱序执行、顺序写回
顺序发射、乱序执行、乱序写回
顺序派遣、乱序发射、乱序执行、乱序写回
分支解析
执行的简化
规整的指令编码格式
优雅的16位指令
精简的指令个数
整数指令的操作数个数是1或2
执行实现
执行指令列表
总体设计思路
译码模块
`include "e203_defines.v"
module e203_exu_decode(
//
// The IR stage to Decoder
input [`E203_INSTR_SIZE-1:0] i_instr, //取指逻辑取回的指令,作为输入等待译码
input [`E203_PC_SIZE-1:0] i_pc, //取值逻辑取回的指令的地址,也就是说取回的这条指令的PC值
input i_prdt_taken,
input i_misalgn, // The fetch misalign 输入的指令总线送过来的信号
input i_buserr, // The fetch bus error 输入的指令总线的错误信号
input i_muldiv_b2b, // The back2back case for mul/div
input dbg_mode, // 指示当前CPU是否处于dbg模式
//
// The Decoded Info-Bus 下面输出译码结果
output dec_rs1x0, //指令的源操作数rs1为X0的指示
output dec_rs2x0, //指令的源操作数rs2为X0的指示
output dec_rs1en, //指令是否需要操作rs1寄存器
output dec_rs2en, //指令是否需要操作rs2寄存器
output dec_rdwen, //指令是否需要操作rd寄存器
output [`E203_RFIDX_WIDTH-1:0] dec_rs1idx, //源操作数rs1的cpu内部地址
output [`E203_RFIDX_WIDTH-1:0] dec_rs2idx, //源操作数rs2的cpu内部地址
output [`E203_RFIDX_WIDTH-1:0] dec_rdidx, //目的操作数rd的cpu内部地址
output [`E203_DECINFO_WIDTH-1:0] dec_info, //解码出的指令信息,用于表示指令具体是啥指令,做啥操作的,方便选通相应的ALU单元
output [`E203_XLEN-1:0] dec_imm, //译码出指令中的立即数
output [`E203_PC_SIZE-1:0] dec_pc, //译码的指令的PC值
output dec_misalgn, //直接根据i_misalgn生成的,如果总线送过来就是misalgn,那么指令就是misalign
output dec_buserr, //根据i_buserr直接生成的
output dec_ilegl, //解析出的指令不合法标记,就是说指令中有些位段是有要求的,比如说立即数中某一bit必须为0,如果不是0,那么就输出不合法等等
output dec_mulhsu, // mul-high-signed-unsigned rs1有符号,rs2无符号,相乘结果(64bit)的高32bit放入rd
output dec_mul , // mul rs1无符号,rs2无符号,(有符号无符号其实是一样的)相乘结果(64bit)的低32bit放入rd
output dec_div , // div rs1有符号,rs2有符号
output dec_rem , // 取 rs1有符号与rs2有符号数,取余数送到dr;
output dec_divu , // 无符号取商送dr
output dec_remu , // 无符号取余送dr
output dec_rv32, //表示当前指令是rsic-v32位指令,还是16位指令
output dec_bjp, //表示当前指令是普通指令还是分支跳转指令,表示是否属于bxx指令或jxx指令的一种
output dec_jal, //属于jal指令
output dec_jalr, //数据jalr指令
output dec_bxx, //属于BXX指令,(BEQ,BNE等带条件分支指令)
output [`E203_RFIDX_WIDTH-1:0] dec_jalr_rs1idx, //针对jalr指令,其首先要取出rs1操作数,然后与立即数相加才能得到值+4作为新的pc,为了取rs1,指令里带了rs1的地址(cpu内部index)
output [`E203_XLEN-1:0] dec_bjp_imm //针对bxx指令,如果条件满足的话,会把12bit立即数(有符号)×2然后与pc相加,作为新的pc;这里是译码出的指令的立即数
);
wire [32-1:0] rv32_instr = i_instr;
wire [16-1:0] rv16_instr = i_instr[15:0];
wire [6:0] opcode = rv32_instr[6:0]; //指令的低7bit为指令的操作码,指示了指令具体是哪一条指令,是做什么操作的
wire opcode_1_0_00 = (opcode[1:0] == 2'b00); // 这里判断操作码的低两位,低两位如果为11的话,说明不是16位指令,否则就是16位指令
wire opcode_1_0_01 = (opcode[1:0] == 2'b01);
wire opcode_1_0_10 = (opcode[1:0] == 2'b10);
wire opcode_1_0_11 = (opcode[1:0] == 2'b11);
wire rv32 = (~(i_instr[4:2] == 3'b111)) & opcode_1_0_11; //指令的[1:0]bit为2'b11,[4:2]bit != 3'b111;那么指令为32位指令
wire [4:0] rv32_rd = rv32_instr[11:7]; //指令编码中[11:7]是指令的目的操作数rd的cpu内部地址索引
wire [2:0] rv32_func3 = rv32_instr[14:12]; //编码指令功能的区域
wire [4:0] rv32_rs1 = rv32_instr[19:15]; //指令的源操作数rs1的cpu内部地址索引
wire [4:0] rv32_rs2 = rv32_instr[24:20]; //指令的源操作数rs2的cpu内部地址索引
wire [6:0] rv32_func7 = rv32_instr[31:25]; //编码指令功能的区域
wire [4:0] rv16_rd = rv32_rd;
wire [4:0] rv16_rs1 = rv16_rd; //16位指令源操作数和目的操作数在同一个位置,关于指令的具体字段含义可以查看书最后的附录F
wire [4:0] rv16_rs2 = rv32_instr[6:2];
wire [4:0] rv16_rdd = {2'b01,rv32_instr[4:2]};
wire [4:0] rv16_rss1 = {2'b01,rv32_instr[9:7]};
wire [4:0] rv16_rss2 = rv16_rdd;
wire [2:0] rv16_func3 = rv32_instr[15:13];
// We generate the signals and reused them as much as possible to save gatecounts
wire opcode_4_2_000 = (opcode[4:2] == 3'b000);
wire opcode_4_2_001 = (opcode[4:2] == 3'b001);
wire opcode_4_2_010 = (opcode[4:2] == 3'b010);
wire opcode_4_2_011 = (opcode[4:2] == 3'b011);
wire opcode_4_2_100 = (opcode[4:2] == 3'b100);
wire opcode_4_2_101 = (opcode[4:2] == 3'b101);
wire opcode_4_2_110 = (opcode[4:2] == 3'b110);
wire opcode_4_2_111 = (opcode[4:2] == 3'b111);
wire opcode_6_5_00 = (opcode[6:5] == 2'b00);
wire opcode_6_5_01 = (opcode[6:5] == 2'b01);
wire opcode_6_5_10 = (opcode[6:5] == 2'b10);
wire opcode_6_5_11 = (opcode[6:5] == 2'b11);
wire rv32_func3_000 = (rv32_func3 == 3'b000);
wire rv32_func3_001 = (rv32_func3 == 3'b001);
wire rv32_func3_010 = (rv32_func3 == 3'b010);
wire rv32_func3_011 = (rv32_func3 == 3'b011);
wire rv32_func3_100 = (rv32_func3 == 3'b100);
wire rv32_func3_101 = (rv32_func3 == 3'b101);
wire rv32_func3_110 = (rv32_func3 == 3'b110);
wire rv32_func3_111 = (rv32_func3 == 3'b111);
wire rv16_func3_000 = (rv16_func3 == 3'b000);
wire rv16_func3_001 = (rv16_func3 == 3'b001);
wire rv16_func3_010 = (rv16_func3 == 3'b010);
wire rv16_func3_011 = (rv16_func3 == 3'b011);
wire rv16_func3_100 = (rv16_func3 == 3'b100);
wire rv16_func3_101 = (rv16_func3 == 3'b101);
wire rv16_func3_110 = (rv16_func3 == 3'b110);
wire rv16_func3_111 = (rv16_func3 == 3'b111);
wire rv32_func7_0000000 = (rv32_func7 == 7'b0000000);
wire rv32_func7_0100000 = (rv32_func7 == 7'b0100000);
wire rv32_func7_0000001 = (rv32_func7 == 7'b0000001);
wire rv32_func7_0000101 = (rv32_func7 == 7'b0000101);
wire rv32_func7_0001001 = (rv32_func7 == 7'b0001001);
wire rv32_func7_0001101 = (rv32_func7 == 7'b0001101);
wire rv32_func7_0010101 = (rv32_func7 == 7'b0010101);
wire rv32_func7_0100001 = (rv32_func7 == 7'b0100001);
wire rv32_func7_0010001 = (rv32_func7 == 7'b0010001);
wire rv32_func7_0101101 = (rv32_func7 == 7'b0101101);
wire rv32_func7_1111111 = (rv32_func7 == 7'b1111111);
wire rv32_func7_0000100 = (rv32_func7 == 7'b0000100);
wire rv32_func7_0001000 = (rv32_func7 == 7'b0001000);
wire rv32_func7_0001100 = (rv32_func7 == 7'b0001100);
wire rv32_func7_0101100 = (rv32_func7 == 7'b0101100);
wire rv32_func7_0010000 = (rv32_func7 == 7'b0010000);
wire rv32_func7_0010100 = (rv32_func7 == 7'b0010100);
wire rv32_func7_1100000 = (rv32_func7 == 7'b1100000);
wire rv32_func7_1110000 = (rv32_func7 == 7'b1110000);
wire rv32_func7_1010000 = (rv32_func7 == 7'b1010000);
wire rv32_func7_1101000 = (rv32_func7 == 7'b1101000);
wire rv32_func7_1111000 = (rv32_func7 == 7'b1111000);
wire rv32_func7_1010001 = (rv32_func7 == 7'b1010001);
wire rv32_func7_1110001 = (rv32_func7 == 7'b1110001);
wire rv32_func7_1100001 = (rv32_func7 == 7'b1100001);
wire rv32_func7_1101001 = (rv32_func7 == 7'b1101001);
wire rv32_rs1_x0 = (rv32_rs1 == 5'b00000); // rs1源操作数是X0
wire rv32_rs2_x0 = (rv32_rs2 == 5'b00000); // rs2源操作数是X0
wire rv32_rs2_x1 = (rv32_rs2 == 5'b00001);
wire rv32_rd_x0 = (rv32_rd == 5'b00000);
wire rv32_rd_x2 = (rv32_rd == 5'b00010);
wire rv16_rs1_x0 = (rv16_rs1 == 5'b00000);
wire rv16_rs2_x0 = (rv16_rs2 == 5'b00000);
wire rv16_rd_x0 = (rv16_rd == 5'b00000);
wire rv16_rd_x2 = (rv16_rd == 5'b00010);
wire rv32_rs1_x31 = (rv32_rs1 == 5'b11111);
wire rv32_rs2_x31 = (rv32_rs2 == 5'b11111);
wire rv32_rd_x31 = (rv32_rd == 5'b11111);
wire rv32_load = opcode_6_5_00 & opcode_4_2_000 & opcode_1_0_11;
wire rv32_store = opcode_6_5_01 & opcode_4_2_000 & opcode_1_0_11;
wire rv32_madd = opcode_6_5_10 & opcode_4_2_000 & opcode_1_0_11;
wire rv32_branch = opcode_6_5_11 & opcode_4_2_000 & opcode_1_0_11;
wire rv32_load_fp = opcode_6_5_00 & opcode_4_2_001 & opcode_1_0_11; // FLW
wire rv32_store_fp = opcode_6_5_01 & opcode_4_2_001 & opcode_1_0_11;
wire rv32_msub = opcode_6_5_10 & opcode_4_2_001 & opcode_1_0_11;
wire rv32_jalr = opcode_6_5_11 & opcode_4_2_001 & opcode_1_0_11;
wire rv32_custom0 = opcode_6_5_00 & opcode_4_2_010 & opcode_1_0_11;
wire rv32_custom1 = opcode_6_5_01 & opcode_4_2_010 & opcode_1_0_11;
wire rv32_nmsub = opcode_6_5_10 & opcode_4_2_010 & opcode_1_0_11;
wire rv32_resved0 = opcode_6_5_11 & opcode_4_2_010 & opcode_1_0_11;
wire rv32_miscmem = opcode_6_5_00 & opcode_4_2_011 & opcode_1_0_11; //00_011_11 FENCE
`ifdef E203_SUPPORT_AMO//{
wire rv32_amo = opcode_6_5_01 & opcode_4_2_011 & opcode_1_0_11; //
`endif//E203_SUPPORT_AMO}
`ifndef E203_SUPPORT_AMO//{
wire rv32_amo = 1'b0;
`endif//}
wire rv32_nmadd = opcode_6_5_10 & opcode_4_2_011 & opcode_1_0_11;
wire rv32_jal = opcode_6_5_11 & opcode_4_2_011 & opcode_1_0_11;
wire rv32_op_imm = opcode_6_5_00 & opcode_4_2_100 & opcode_1_0_11;
wire rv32_op = opcode_6_5_01 & opcode_4_2_100 & opcode_1_0_11;
wire rv32_op_fp = opcode_6_5_10 & opcode_4_2_100 & opcode_1_0_11;
wire rv32_system = opcode_6_5_11 & opcode_4_2_100 & opcode_1_0_11;
wire rv32_auipc = opcode_6_5_00 & opcode_4_2_101 & opcode_1_0_11;
wire rv32_lui = opcode_6_5_01 & opcode_4_2_101 & opcode_1_0_11;
wire rv32_resved1 = opcode_6_5_10 & opcode_4_2_101 & opcode_1_0_11;
wire rv32_resved2 = opcode_6_5_11 & opcode_4_2_101 & opcode_1_0_11;
wire rv32_op_imm_32= opcode_6_5_00 & opcode_4_2_110 & opcode_1_0_11;
wire rv32_op_32 = opcode_6_5_01 & opcode_4_2_110 & opcode_1_0_11;
wire rv32_custom2 = opcode_6_5_10 & opcode_4_2_110 & opcode_1_0_11;
wire rv32_custom3 = opcode_6_5_11 & opcode_4_2_110 & opcode_1_0_11;
wire rv16_addi4spn = opcode_1_0_00 & rv16_func3_000;//
wire rv16_lw = opcode_1_0_00 & rv16_func3_010;//
wire rv16_sw = opcode_1_0_00 & rv16_func3_110;//
wire rv16_addi = opcode_1_0_01 & rv16_func3_000;//
wire rv16_jal = opcode_1_0_01 & rv16_func3_001;//
wire rv16_li = opcode_1_0_01 & rv16_func3_010;//
wire rv16_lui_addi16sp = opcode_1_0_01 & rv16_func3_011;//--
wire rv16_miscalu = opcode_1_0_01 & rv16_func3_100;//--
wire rv16_j = opcode_1_0_01 & rv16_func3_101;//
wire rv16_beqz = opcode_1_0_01 & rv16_func3_110;//
wire rv16_bnez = opcode_1_0_01 & rv16_func3_111;//
wire rv16_slli = opcode_1_0_10 & rv16_func3_000;//
wire rv16_lwsp = opcode_1_0_10 & rv16_func3_010;//
wire rv16_jalr_mv_add = opcode_1_0_10 & rv16_func3_100;//--
wire rv16_swsp = opcode_1_0_10 & rv16_func3_110;//
`ifndef E203_HAS_FPU//{
wire rv16_flw = 1'b0;
wire rv16_fld = 1'b0;
wire rv16_fsw = 1'b0;
wire rv16_fsd = 1'b0;
wire rv16_fldsp = 1'b0;
wire rv16_flwsp = 1'b0;
wire rv16_fsdsp = 1'b0;
wire rv16_fswsp = 1'b0;
`endif//}
wire rv16_lwsp_ilgl = rv16_lwsp & rv16_rd_x0;//(RES, rd=0) lwsp指令非法指示,16bit lwsp指令要求rd不能为0,就是rd不能为X0,因为X0固定接0
wire rv16_nop = rv16_addi
& (~rv16_instr[12]) & (rv16_rd_x0) & (rv16_rs2_x0);
wire rv16_srli = rv16_miscalu & (rv16_instr[11:10] == 2'b00);
wire rv16_srai = rv16_miscalu & (rv16_instr[11:10] == 2'b01);
wire rv16_andi = rv16_miscalu & (rv16_instr[11:10] == 2'b10);
wire rv16_instr_12_is0 = (rv16_instr[12] == 1'b0);
wire rv16_instr_6_2_is0s = (rv16_instr[6:2] == 5'b0);
wire rv16_sxxi_shamt_legl =
rv16_instr_12_is0 //shamt[5] must be zero for RV32C
& (~(rv16_instr_6_2_is0s)) //shamt[4:0] must be non-zero for RV32C
;
wire rv16_sxxi_shamt_ilgl = (rv16_slli | rv16_srli | rv16_srai) & (~rv16_sxxi_shamt_legl); //检查sxxi类型的指令是否合法
wire rv16_addi16sp = rv16_lui_addi16sp & rv32_rd_x2;// 检测操作的是不是X2(stack pointer),如果是2的话,那么是addi16sp指令
wire rv16_lui = rv16_lui_addi16sp & (~rv32_rd_x0) & (~rv32_rd_x2);// 如果rd不是x0或x2,那么是lui指令
//C.LI is only valid when rd!=x0.
wire rv16_li_ilgl = rv16_li & (rv16_rd_x0);
//C.LUI is only valid when rd!=x0 or x2, and when the immediate is not equal to zero.
wire rv16_lui_ilgl = rv16_lui & (rv16_rd_x0 | rv16_rd_x2 | (rv16_instr_6_2_is0s & rv16_instr_12_is0));
wire rv16_li_lui_ilgl = rv16_li_ilgl | rv16_lui_ilgl;
wire rv16_addi4spn_ilgl = rv16_addi4spn & (rv16_instr_12_is0 & rv16_rd_x0 & opcode_6_5_00);//(RES, nzimm=0, bits[12:5])
wire rv16_addi16sp_ilgl = rv16_addi16sp & rv16_instr_12_is0 & rv16_instr_6_2_is0s; //(RES, nzimm=0, bits 12,6:2)
wire rv16_subxororand = rv16_miscalu & (rv16_instr[12:10] == 3'b011);//
wire rv16_sub = rv16_subxororand & (rv16_instr[6:5] == 2'b00);//
wire rv16_xor = rv16_subxororand & (rv16_instr[6:5] == 2'b01);//
wire rv16_or = rv16_subxororand & (rv16_instr[6:5] == 2'b10);//
wire rv16_and = rv16_subxororand & (rv16_instr[6:5] == 2'b11);//
wire rv16_jr = rv16_jalr_mv_add //
& (~rv16_instr[12]) & (~rv16_rs1_x0) & (rv16_rs2_x0);// The RES rs1=0 illegal is already covered here
wire rv16_mv = rv16_jalr_mv_add //
& (~rv16_instr[12]) & (~rv16_rd_x0) & (~rv16_rs2_x0);
wire rv16_ebreak = rv16_jalr_mv_add //
& (rv16_instr[12]) & (rv16_rd_x0) & (rv16_rs2_x0);
wire rv16_jalr = rv16_jalr_mv_add //
& (rv16_instr[12]) & (~rv16_rs1_x0) & (rv16_rs2_x0);
wire rv16_add = rv16_jalr_mv_add //
& (rv16_instr[12]) & (~rv16_rd_x0) & (~rv16_rs2_x0);
// ===========================================================================
// Branch Instructions
wire rv32_beq = rv32_branch & rv32_func3_000; //
wire rv32_bne = rv32_branch & rv32_func3_001; //
wire rv32_blt = rv32_branch & rv32_func3_100;
wire rv32_bgt = rv32_branch & rv32_func3_101;
wire rv32_bltu = rv32_branch & rv32_func3_110;
wire rv32_bgtu = rv32_branch & rv32_func3_111;
// ===========================================================================
// System Instructions
wire rv32_ecall = rv32_system & rv32_func3_000 & (rv32_instr[31:20] == 12'b0000_0000_0000);
wire rv32_ebreak = rv32_system & rv32_func3_000 & (rv32_instr[31:20] == 12'b0000_0000_0001);
wire rv32_mret = rv32_system & rv32_func3_000 & (rv32_instr[31:20] == 12'b0011_0000_0010);
wire rv32_dret = rv32_system & rv32_func3_000 & (rv32_instr[31:20] == 12'b0111_1011_0010); // debug return 这个指令不知道是自定义的还是附录F里漏了?
wire rv32_wfi = rv32_system & rv32_func3_000 & (rv32_instr[31:20] == 12'b0001_0000_0101);
// We dont implement the WFI and MRET illegal exception when the rs and rd is not zeros
wire rv32_csrrw = rv32_system & rv32_func3_001;
wire rv32_csrrs = rv32_system & rv32_func3_010;
wire rv32_csrrc = rv32_system & rv32_func3_011;
wire rv32_csrrwi = rv32_system & rv32_func3_101;
wire rv32_csrrsi = rv32_system & rv32_func3_110;
wire rv32_csrrci = rv32_system & rv32_func3_111;
wire rv32_dret_ilgl = rv32_dret & (~dbg_mode); // 如果非debug mode下收到这条指令,认为这条指令是非法的
wire rv32_ecall_ebreak_ret_wfi = rv32_system & rv32_func3_000; //表示是否是 ecall、ebreak、ret、wfi里面的一种
wire rv32_csr = rv32_system & (~rv32_func3_000); //表示是否是csr指令的一种
// ===========================================================================
// The Branch and system group of instructions will be handled by BJP
assign dec_jal = rv32_jal | rv16_jal | rv16_j; //是否是jal 上面这个不需要从r里取内容
assign dec_jalr = rv32_jalr | rv16_jalr | rv16_jr; //是否是jalr 跟上面的区别是是否直接跳转,这个要从r里取内容再相加pc和立即数才能得地址
assign dec_bxx = rv32_branch | rv16_beqz | rv16_bnez; //bxx指令是带条件的跳转指令,跳不跳要看条件满不满足
assign dec_bjp = dec_jal | dec_jalr | dec_bxx; //是否是跳转指令,只要是上面三种跳转指令里面的一种
wire rv32_fence ;
wire rv32_fence_i;
wire rv32_fence_fencei;
wire bjp_op = dec_bjp | rv32_mret | (rv32_dret & (~rv32_dret_ilgl)) | rv32_fence_fencei;
wire [`E203_DECINFO_BJP_WIDTH-1:0] bjp_info_bus; // bjp 信息汇总为一条bus
assign bjp_info_bus[`E203_DECINFO_GRP ] = `E203_DECINFO_GRP_BJP;
assign bjp_info_bus[`E203_DECINFO_RV32 ] = rv32; //是否是32bit指令
assign bjp_info_bus[`E203_DECINFO_BJP_JUMP ] = dec_jal | dec_jalr; //是否是无条件跳转指令
assign bjp_info_bus[`E203_DECINFO_BJP_BPRDT] = i_prdt_taken; //分支预测是否take,即预测是跳转还是不跳转,taken表示跳转
assign bjp_info_bus[`E203_DECINFO_BJP_BEQ ] = rv32_beq | rv16_beqz; //相等跳转
assign bjp_info_bus[`E203_DECINFO_BJP_BNE ] = rv32_bne | rv16_bnez; //不相等跳转
assign bjp_info_bus[`E203_DECINFO_BJP_BLT ] = rv32_blt; //小于跳转
assign bjp_info_bus[`E203_DECINFO_BJP_BGT ] = rv32_bgt ; //大于跳转
assign bjp_info_bus[`E203_DECINFO_BJP_BLTU ] = rv32_bltu; //无符号小于跳转
assign bjp_info_bus[`E203_DECINFO_BJP_BGTU ] = rv32_bgtu; //无符号大于跳转
assign bjp_info_bus[`E203_DECINFO_BJP_BXX ] = dec_bxx; //是否是跳转指令
assign bjp_info_bus[`E203_DECINFO_BJP_MRET ] = rv32_mret; //是否是message return 是不是理解成唤醒状态,或者中断返回也是跳转?
assign bjp_info_bus[`E203_DECINFO_BJP_DRET ] = rv32_dret; //是否是debug return
assign bjp_info_bus[`E203_DECINFO_BJP_FENCE ] = rv32_fence; //是否是数据store屏蔽指令
assign bjp_info_bus[`E203_DECINFO_BJP_FENCEI] = rv32_fence_i; //是否是指令store屏蔽指令
// ===========================================================================
// ALU Instructions //生成算术运算指令的具体类型,每个指令对应一个flag信号。给alu
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);
wire rv32_sxxi_shamt_legl = (rv32_instr[25] == 1'b0); //shamt[5] must be zero for RV32I
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;
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;
wire alu_op = (~rv32_sxxi_shamt_ilgl) & (~rv16_sxxi_shamt_ilgl) // alu_op表示ALU需要动作,当为下面这些指令且指令有效的时候ALU需要做操作
& (~rv16_li_lui_ilgl) & (~rv16_addi4spn_ilgl) & (~rv16_addi16sp_ilgl) &
( rv32_op_imm
| rv32_op & (~rv32_func7_0000001) // Exclude the MULDIV 这里排除了乘法和除法指令,因为乘除法指令不是一个ALU周期能够完成的
| 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; //生成给ALU的相关信息的bus
assign alu_info_bus[`E203_DECINFO_GRP ] = `E203_DECINFO_GRP_ALU; // 这个DECINFO_GRP用来指示,当前指令属于哪一大类,比如是ALU还是BJP等
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;
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];
// ===========================================================================
// Memory Order Instructions
assign rv32_fence = rv32_miscmem & rv32_func3_000;
assign rv32_fence_i = rv32_miscmem & rv32_func3_001;
assign rv32_fence_fencei = rv32_miscmem;
// ===========================================================================
// 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_rem = rv32_divu;
assign dec_divu = rv32_rem;
assign dec_remu = rv32_remu;
// ===========================================================================
// 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;
// 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);
//
// All the RV32IMA need RD register except the
// * Branch, Store,
// * fence, fence_i
// * ecall, ebreak
wire rv32_need_rd = // rv32的指令里面,如果不是下面这些指令,而且rd不是x0的话,就需要有目的操作数寄存器,即这个flag指示是否需要对目的操作数寄存器进行操作
(~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的话,就需要有源操作数寄存器,即这个flag指示是否需要对源操作数寄存器进行操作
(~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) & ( //是否有rs2操作数
(
(rv32_branch)
| (rv32_store)
| (rv32_op)
| (rv32_amo & (~rv32_lr_w))
)
);
wire [31:0] rv32_i_imm = { // rv32_op_imm | rv32_jalr | rv32_load 这三类指令的立即数
{20{rv32_instr[31]}}
, rv32_instr[31:20]
};
wire [31:0] rv32_s_imm = { // SB、SH、SW这三个指令的立即数
{20{rv32_instr[31]}}
, rv32_instr[31:25]
, rv32_instr[11:7]
};
wire [31:0] rv32_b_imm = { //BEQ、BNE、BLT、BGE、BLTU、BGEU等指令的立即数
{19{rv32_instr[31]}}
, rv32_instr[31]
, rv32_instr[7]
, rv32_instr[30:25]
, rv32_instr[11:8]
, 1'b0
};
wire [31:0] rv32_u_imm = {rv32_instr[31:12],12'b0}; //LUI、AUIPC等指令的立即数
wire [31:0] rv32_j_imm = { //JAL 指令的立即数
{11{rv32_instr[31]}}
, rv32_instr[31]
, rv32_instr[19:12]
, rv32_instr[20]
, rv32_instr[30:21]
, 1'b0
};
// It will select i-type immediate when
// * rv32_op_imm
// * rv32_jalr
// * rv32_load
wire rv32_imm_sel_i = rv32_op_imm | rv32_jalr | rv32_load; //表示指令的立即数是rv32_i_imm
wire rv32_imm_sel_jalr = rv32_jalr; //表示当前指令的立即数是rv32_j_imm ,下同;即不同类型的指令,立即数的位置不一样
wire [31:0] rv32_jalr_imm = rv32_i_imm;
// It will select u-type immediate when
// * rv32_lui, rv32_auipc
wire rv32_imm_sel_u = rv32_lui | rv32_auipc;
// It will select j-type immediate when
// * rv32_jal
wire rv32_imm_sel_j = rv32_jal;
wire rv32_imm_sel_jal = rv32_jal;
wire [31:0] rv32_jal_imm = rv32_j_imm;
// It will select b-type immediate when
// * rv32_branch
wire rv32_imm_sel_b = rv32_branch;
wire rv32_imm_sel_bxx = rv32_branch;
wire [31:0] rv32_bxx_imm = rv32_b_imm;
// It will select s-type immediate when
// * rv32_store
wire rv32_imm_sel_s = rv32_store;
// * Note: this CIS/CILI/CILUI/CI16SP-type is named by myself, because in
// ISA doc, the CI format for LWSP is different
// with other CI formats in terms of immediate
// It will select CIS-type immediate when
// * rv16_lwsp
wire rv16_imm_sel_cis = rv16_lwsp;
wire [31:0] rv16_cis_imm ={
24'b0
, rv16_instr[3:2]
, rv16_instr[12]
, rv16_instr[6:4]
, 2'b0
};
wire [31:0] rv16_cis_d_imm ={
23'b0
, rv16_instr[4:2]
, rv16_instr[12]
, rv16_instr[6:5]
, 3'b0
};
// It will select CILI-type immediate when
// * rv16_li
// * rv16_addi
// * rv16_slli
// * rv16_srai
// * rv16_srli
// * rv16_andi
wire rv16_imm_sel_cili = rv16_li | rv16_addi | rv16_slli
| rv16_srai | rv16_srli | rv16_andi;
wire [31:0] rv16_cili_imm ={
{26{rv16_instr[12]}}
, rv16_instr[12]
, rv16_instr[6:2]
};
// It will select CILUI-type immediate when
// * rv16_lui
wire rv16_imm_sel_cilui = rv16_lui;
wire [31:0] rv16_cilui_imm ={
{14{rv16_instr[12]}}
, rv16_instr[12]
, rv16_instr[6:2]
, 12'b0
};
// It will select CI16SP-type immediate when
// * rv16_addi16sp
wire rv16_imm_sel_ci16sp = rv16_addi16sp;
wire [31:0] rv16_ci16sp_imm ={
{22{rv16_instr[12]}}
, rv16_instr[12]
, rv16_instr[4]
, rv16_instr[3]
, rv16_instr[5]
, rv16_instr[2]
, rv16_instr[6]
, 4'b0
};
// It will select CSS-type immediate when
// * rv16_swsp
wire rv16_imm_sel_css = rv16_swsp;
wire [31:0] rv16_css_imm ={
24'b0
, rv16_instr[8:7]
, rv16_instr[12:9]
, 2'b0
};
wire [31:0] rv16_css_d_imm ={
23'b0
, rv16_instr[9:7]
, rv16_instr[12:10]
, 3'b0
};
// It will select CIW-type immediate when
// * rv16_addi4spn
wire rv16_imm_sel_ciw = rv16_addi4spn;
wire [31:0] rv16_ciw_imm ={
22'b0
, rv16_instr[10:7]
, rv16_instr[12]
, rv16_instr[11]
, rv16_instr[5]
, rv16_instr[6]
, 2'b0
};
// It will select CL-type immediate when
// * rv16_lw
wire rv16_imm_sel_cl = rv16_lw;
wire [31:0] rv16_cl_imm ={
25'b0
, rv16_instr[5]
, rv16_instr[12]
, rv16_instr[11]
, rv16_instr[10]
, rv16_instr[6]
, 2'b0
};
wire [31:0] rv16_cl_d_imm ={
24'b0
, rv16_instr[6]
, rv16_instr[5]
, rv16_instr[12]
, rv16_instr[11]
, rv16_instr[10]
, 3'b0
};
// It will select CS-type immediate when
// * rv16_sw
wire rv16_imm_sel_cs = rv16_sw;
wire [31:0] rv16_cs_imm ={
25'b0
, rv16_instr[5]
, rv16_instr[12]
, rv16_instr[11]
, rv16_instr[10]
, rv16_instr[6]
, 2'b0
};
wire [31:0] rv16_cs_d_imm ={
24'b0
, rv16_instr[6]
, rv16_instr[5]
, rv16_instr[12]
, rv16_instr[11]
, rv16_instr[10]
, 3'b0
};
// It will select CB-type immediate when
// * rv16_beqz
// * rv16_bnez
wire rv16_imm_sel_cb = rv16_beqz | rv16_bnez;
wire [31:0] rv16_cb_imm ={
{23{rv16_instr[12]}}
, rv16_instr[12]
, rv16_instr[6:5]
, rv16_instr[2]
, rv16_instr[11:10]
, rv16_instr[4:3]
, 1'b0
};
wire [31:0] rv16_bxx_imm = rv16_cb_imm;
// It will select CJ-type immediate when
// * rv16_j
// * rv16_jal
wire rv16_imm_sel_cj = rv16_j | rv16_jal;
wire [31:0] rv16_cj_imm ={
{20{rv16_instr[12]}}
, rv16_instr[12]
, rv16_instr[8]
, rv16_instr[10:9]
, rv16_instr[6]
, rv16_instr[7]
, rv16_instr[2]
, rv16_instr[11]
, rv16_instr[5:3]
, 1'b0
};
wire [31:0] rv16_jjal_imm = rv16_cj_imm;
// It will select CR-type register (no-imm) when
// * rv16_jalr_mv_add
wire [31:0] rv16_jrjalr_imm = 32'b0;
// It will select CSR-type register (no-imm) when
// * rv16_subxororand
wire [31:0] rv32_load_fp_imm = rv32_i_imm; // FLW 指令的立即数
wire [31:0] rv32_store_fp_imm = rv32_s_imm; // FSW 指令的立即数
wire [31:0] rv32_imm = // 根据译码得来的指令的具体类型,生成最终的操作数
({32{rv32_imm_sel_i}} & rv32_i_imm)
| ({32{rv32_imm_sel_s}} & rv32_s_imm)
| ({32{rv32_imm_sel_b}} & rv32_b_imm)
| ({32{rv32_imm_sel_u}} & rv32_u_imm)
| ({32{rv32_imm_sel_j}} & rv32_j_imm)
;
wire rv32_need_imm = // 只有指令是下面这些类型的时候才需要操作数
rv32_imm_sel_i
| rv32_imm_sel_s
| rv32_imm_sel_b
| rv32_imm_sel_u
| rv32_imm_sel_j
;
wire [31:0] rv16_imm =
({32{rv16_imm_sel_cis }} & rv16_cis_imm)
| ({32{rv16_imm_sel_cili }} & rv16_cili_imm)
| ({32{rv16_imm_sel_cilui }} & rv16_cilui_imm)
| ({32{rv16_imm_sel_ci16sp}} & rv16_ci16sp_imm)
| ({32{rv16_imm_sel_css }} & rv16_css_imm)
| ({32{rv16_imm_sel_ciw }} & rv16_ciw_imm)
| ({32{rv16_imm_sel_cl }} & rv16_cl_imm)
| ({32{rv16_imm_sel_cs }} & rv16_cs_imm)
| ({32{rv16_imm_sel_cb }} & rv16_cb_imm)
| ({32{rv16_imm_sel_cj }} & rv16_cj_imm)
;
wire rv16_need_imm =
rv16_imm_sel_cis
| rv16_imm_sel_cili
| rv16_imm_sel_cilui
| rv16_imm_sel_ci16sp
| rv16_imm_sel_css
| rv16_imm_sel_ciw
| rv16_imm_sel_cl
| rv16_imm_sel_cs
| rv16_imm_sel_cb
| rv16_imm_sel_cj
;
assign need_imm = rv32 ? rv32_need_imm : rv16_need_imm; //指令需不需要立即数(就是指令指示的操作需要立即数,指令里带了立即数,要提出来)
assign dec_imm = rv32 ? rv32_imm : rv16_imm; //从指令的相应位段里解码出来的指令的立即数
assign dec_pc = i_pc; // 当前译码的指令所在的PC值
assign dec_info = // 输出的译码结果信息,至少一个信息会输出,其余都是0
({`E203_DECINFO_WIDTH{alu_op}} & {{`E203_DECINFO_WIDTH-`E203_DECINFO_ALU_WIDTH{1'b0}},alu_info_bus})
| ({`E203_DECINFO_WIDTH{amoldst_op}} & {{`E203_DECINFO_WIDTH-`E203_DECINFO_AGU_WIDTH{1'b0}},agu_info_bus})
| ({`E203_DECINFO_WIDTH{bjp_op}} & {{`E203_DECINFO_WIDTH-`E203_DECINFO_BJP_WIDTH{1'b0}},bjp_info_bus})
| ({`E203_DECINFO_WIDTH{csr_op}} & {{`E203_DECINFO_WIDTH-`E203_DECINFO_CSR_WIDTH{1'b0}},csr_info_bus})
| ({`E203_DECINFO_WIDTH{muldiv_op}} & {{`E203_DECINFO_WIDTH-`E203_DECINFO_CSR_WIDTH{1'b0}},muldiv_info_bus})
;
wire legl_ops = //输出的译码结果是否合法,合法则至少一个1
alu_op
| amoldst_op
| bjp_op
| csr_op
| muldiv_op
;
// To decode the registers for Rv16, divided into 8 groups
wire rv16_format_cr = rv16_jalr_mv_add;
wire rv16_format_ci = rv16_lwsp | rv16_flwsp | rv16_fldsp | rv16_li | rv16_lui_addi16sp | rv16_addi | rv16_slli;
wire rv16_format_css = rv16_swsp | rv16_fswsp | rv16_fsdsp;
wire rv16_format_ciw = rv16_addi4spn;
wire rv16_format_cl = rv16_lw | rv16_flw | rv16_fld;
wire rv16_format_cs = rv16_sw | rv16_fsw | rv16_fsd | rv16_subxororand;
wire rv16_format_cb = rv16_beqz | rv16_bnez | rv16_srli | rv16_srai | rv16_andi;
wire rv16_format_cj = rv16_j | rv16_jal;
// In CR Cases:
// * JR: rs1= rs1(coded), rs2= x0 (coded), rd = x0 (implicit)
// * JALR: rs1= rs1(coded), rs2= x0 (coded), rd = x1 (implicit)
// * MV: rs1= x0 (implicit), rs2= rs2(coded), rd = rd (coded)
// * ADD: rs1= rs1(coded), rs2= rs2(coded), rd = rd (coded)
// * eBreak: rs1= rs1(coded), rs2= x0 (coded), rd = x0 (coded)
wire rv16_need_cr_rs1 = rv16_format_cr & 1'b1;
wire rv16_need_cr_rs2 = rv16_format_cr & 1'b1;
wire rv16_need_cr_rd = rv16_format_cr & 1'b1;
wire [`E203_RFIDX_WIDTH-1:0] rv16_cr_rs1 = rv16_mv ? `E203_RFIDX_WIDTH'd0 : rv16_rs1[`E203_RFIDX_WIDTH-1:0];
wire [`E203_RFIDX_WIDTH-1:0] rv16_cr_rs2 = rv16_rs2[`E203_RFIDX_WIDTH-1:0];
// The JALR and JR difference in encoding is just the rv16_instr[12]
wire [`E203_RFIDX_WIDTH-1:0] rv16_cr_rd = (rv16_jalr | rv16_jr)?
{{`E203_RFIDX_WIDTH-1{1'b0}},rv16_instr[12]} : rv16_rd[`E203_RFIDX_WIDTH-1:0];
// In CI Cases:
// * LWSP: rs1= x2 (implicit), rd = rd
// * LI/LUI: rs1= x0 (implicit), rd = rd
// * ADDI: rs1= rs1(implicit), rd = rd
// * ADDI16SP: rs1= rs1(implicit), rd = rd
// * SLLI: rs1= rs1(implicit), rd = rd
wire rv16_need_ci_rs1 = rv16_format_ci & 1'b1;
wire rv16_need_ci_rs2 = rv16_format_ci & 1'b0;
wire rv16_need_ci_rd = rv16_format_ci & 1'b1;
wire [`E203_RFIDX_WIDTH-1:0] rv16_ci_rs1 = (rv16_lwsp | rv16_flwsp | rv16_fldsp) ? `E203_RFIDX_WIDTH'd2 :
(rv16_li | rv16_lui) ? `E203_RFIDX_WIDTH'd0 : rv16_rs1[`E203_RFIDX_WIDTH-1:0];
wire [`E203_RFIDX_WIDTH-1:0] rv16_ci_rs2 = `E203_RFIDX_WIDTH'd0;
wire [`E203_RFIDX_WIDTH-1:0] rv16_ci_rd = rv16_rd[`E203_RFIDX_WIDTH-1:0];
// In CSS Cases:
// * SWSP: rs1 = x2 (implicit), rs2= rs2
wire rv16_need_css_rs1 = rv16_format_css & 1'b1;
wire rv16_need_css_rs2 = rv16_format_css & 1'b1;
wire rv16_need_css_rd = rv16_format_css & 1'b0;
wire [`E203_RFIDX_WIDTH-1:0] rv16_css_rs1 = `E203_RFIDX_WIDTH'd2;
wire [`E203_RFIDX_WIDTH-1:0] rv16_css_rs2 = rv16_rs2[`E203_RFIDX_WIDTH-1:0];
wire [`E203_RFIDX_WIDTH-1:0] rv16_css_rd = `E203_RFIDX_WIDTH'd0;
// In CIW cases:
// * ADDI4SPN: rdd = rdd, rss1= x2 (implicit)
wire rv16_need_ciw_rss1 = rv16_format_ciw & 1'b1;
wire rv16_need_ciw_rss2 = rv16_format_ciw & 1'b0;
wire rv16_need_ciw_rdd = rv16_format_ciw & 1'b1;
wire [`E203_RFIDX_WIDTH-1:0] rv16_ciw_rss1 = `E203_RFIDX_WIDTH'd2;
wire [`E203_RFIDX_WIDTH-1:0] rv16_ciw_rss2 = `E203_RFIDX_WIDTH'd0;
wire [`E203_RFIDX_WIDTH-1:0] rv16_ciw_rdd = rv16_rdd[`E203_RFIDX_WIDTH-1:0];
// In CL cases:
// * LW: rss1 = rss1, rdd= rdd
wire rv16_need_cl_rss1 = rv16_format_cl & 1'b1;
wire rv16_need_cl_rss2 = rv16_format_cl & 1'b0;
wire rv16_need_cl_rdd = rv16_format_cl & 1'b1;
wire [`E203_RFIDX_WIDTH-1:0] rv16_cl_rss1 = rv16_rss1[`E203_RFIDX_WIDTH-1:0];
wire [`E203_RFIDX_WIDTH-1:0] rv16_cl_rss2 = `E203_RFIDX_WIDTH'd0;
wire [`E203_RFIDX_WIDTH-1:0] rv16_cl_rdd = rv16_rdd[`E203_RFIDX_WIDTH-1:0];
// In CS cases:
// * SW: rdd = none(implicit), rss1= rss1 , rss2=rss2
// * SUBXORORAND: rdd = rss1, rss1= rss1(coded), rss2=rss2
wire rv16_need_cs_rss1 = rv16_format_cs & 1'b1;
wire rv16_need_cs_rss2 = rv16_format_cs & 1'b1;
wire rv16_need_cs_rdd = rv16_format_cs & rv16_subxororand;
wire [`E203_RFIDX_WIDTH-1:0] rv16_cs_rss1 = rv16_rss1[`E203_RFIDX_WIDTH-1:0];
wire [`E203_RFIDX_WIDTH-1:0] rv16_cs_rss2 = rv16_rss2[`E203_RFIDX_WIDTH-1:0];
wire [`E203_RFIDX_WIDTH-1:0] rv16_cs_rdd = rv16_rss1[`E203_RFIDX_WIDTH-1:0];
// In CB cases:
// * BEQ/BNE: rdd = none(implicit), rss1= rss1, rss2=x0(implicit)
// * SRLI/SRAI/ANDI: rdd = rss1 , rss1= rss1, rss2=none(implicit)
wire rv16_need_cb_rss1 = rv16_format_cb & 1'b1;
wire rv16_need_cb_rss2 = rv16_format_cb & (rv16_beqz | rv16_bnez);
wire rv16_need_cb_rdd = rv16_format_cb & (~(rv16_beqz | rv16_bnez));
wire [`E203_RFIDX_WIDTH-1:0] rv16_cb_rss1 = rv16_rss1[`E203_RFIDX_WIDTH-1:0];
wire [`E203_RFIDX_WIDTH-1:0] rv16_cb_rss2 = `E203_RFIDX_WIDTH'd0;
wire [`E203_RFIDX_WIDTH-1:0] rv16_cb_rdd = rv16_rss1[`E203_RFIDX_WIDTH-1:0];
// In CJ cases:
// * J: rdd = x0(implicit)
// * JAL: rdd = x1(implicit)
wire rv16_need_cj_rss1 = rv16_format_cj & 1'b0;
wire rv16_need_cj_rss2 = rv16_format_cj & 1'b0;
wire rv16_need_cj_rdd = rv16_format_cj & 1'b1;
wire [`E203_RFIDX_WIDTH-1:0] rv16_cj_rss1 = `E203_RFIDX_WIDTH'd0;
wire [`E203_RFIDX_WIDTH-1:0] rv16_cj_rss2 = `E203_RFIDX_WIDTH'd0;
wire [`E203_RFIDX_WIDTH-1:0] rv16_cj_rdd = rv16_j ? `E203_RFIDX_WIDTH'd0 : `E203_RFIDX_WIDTH'd1;
// rv16_format_cr
// rv16_format_ci
// rv16_format_css
// rv16_format_ciw
// rv16_format_cl
// rv16_format_cs
// rv16_format_cb
// rv16_format_cj
wire rv16_need_rs1 = rv16_need_cr_rs1 | rv16_need_ci_rs1 | rv16_need_css_rs1;
wire rv16_need_rs2 = rv16_need_cr_rs2 | rv16_need_ci_rs2 | rv16_need_css_rs2;
wire rv16_need_rd = rv16_need_cr_rd | rv16_need_ci_rd | rv16_need_css_rd;
wire rv16_need_rss1 = rv16_need_ciw_rss1|rv16_need_cl_rss1|rv16_need_cs_rss1|rv16_need_cb_rss1|rv16_need_cj_rss1;
wire rv16_need_rss2 = rv16_need_ciw_rss2|rv16_need_cl_rss2|rv16_need_cs_rss2|rv16_need_cb_rss2|rv16_need_cj_rss2;
wire rv16_need_rdd = rv16_need_ciw_rdd |rv16_need_cl_rdd |rv16_need_cs_rdd |rv16_need_cb_rdd |rv16_need_cj_rdd ;
wire rv16_rs1en = (rv16_need_rs1 | rv16_need_rss1);
wire rv16_rs2en = (rv16_need_rs2 | rv16_need_rss2);
wire rv16_rden = (rv16_need_rd | rv16_need_rdd );
wire [`E203_RFIDX_WIDTH-1:0] rv16_rs1idx;
wire [`E203_RFIDX_WIDTH-1:0] rv16_rs2idx;
wire [`E203_RFIDX_WIDTH-1:0] rv16_rdidx ;
assign rv16_rs1idx =
({`E203_RFIDX_WIDTH{rv16_need_cr_rs1 }} & rv16_cr_rs1)
| ({`E203_RFIDX_WIDTH{rv16_need_ci_rs1 }} & rv16_ci_rs1)
| ({`E203_RFIDX_WIDTH{rv16_need_css_rs1}} & rv16_css_rs1)
| ({`E203_RFIDX_WIDTH{rv16_need_ciw_rss1}} & rv16_ciw_rss1)
| ({`E203_RFIDX_WIDTH{rv16_need_cl_rss1}} & rv16_cl_rss1)
| ({`E203_RFIDX_WIDTH{rv16_need_cs_rss1}} & rv16_cs_rss1)
| ({`E203_RFIDX_WIDTH{rv16_need_cb_rss1}} & rv16_cb_rss1)
| ({`E203_RFIDX_WIDTH{rv16_need_cj_rss1}} & rv16_cj_rss1)
;
assign rv16_rs2idx =
({`E203_RFIDX_WIDTH{rv16_need_cr_rs2 }} & rv16_cr_rs2)
| ({`E203_RFIDX_WIDTH{rv16_need_ci_rs2 }} & rv16_ci_rs2)
| ({`E203_RFIDX_WIDTH{rv16_need_css_rs2}} & rv16_css_rs2)
| ({`E203_RFIDX_WIDTH{rv16_need_ciw_rss2}} & rv16_ciw_rss2)
| ({`E203_RFIDX_WIDTH{rv16_need_cl_rss2}} & rv16_cl_rss2)
| ({`E203_RFIDX_WIDTH{rv16_need_cs_rss2}} & rv16_cs_rss2)
| ({`E203_RFIDX_WIDTH{rv16_need_cb_rss2}} & rv16_cb_rss2)
| ({`E203_RFIDX_WIDTH{rv16_need_cj_rss2}} & rv16_cj_rss2)
;
assign rv16_rdidx =
({`E203_RFIDX_WIDTH{rv16_need_cr_rd }} & rv16_cr_rd)
| ({`E203_RFIDX_WIDTH{rv16_need_ci_rd }} & rv16_ci_rd)
| ({`E203_RFIDX_WIDTH{rv16_need_css_rd}} & rv16_css_rd)
| ({`E203_RFIDX_WIDTH{rv16_need_ciw_rdd}} & rv16_ciw_rdd)
| ({`E203_RFIDX_WIDTH{rv16_need_cl_rdd}} & rv16_cl_rdd)
| ({`E203_RFIDX_WIDTH{rv16_need_cs_rdd}} & rv16_cs_rdd)
| ({`E203_RFIDX_WIDTH{rv16_need_cb_rdd}} & rv16_cb_rdd)
| ({`E203_RFIDX_WIDTH{rv16_need_cj_rdd}} & rv16_cj_rdd)
;
assign dec_rs1idx = rv32 ? rv32_rs1[`E203_RFIDX_WIDTH-1:0] : rv16_rs1idx; // 最终输出的指令的译码结果,rs1的indx rs2的index 以及 rd的index
assign dec_rs2idx = rv32 ? rv32_rs2[`E203_RFIDX_WIDTH-1:0] : rv16_rs2idx;
assign dec_rdidx = rv32 ? rv32_rd [`E203_RFIDX_WIDTH-1:0] : rv16_rdidx ;
assign dec_rs1en = rv32 ? rv32_need_rs1 : (rv16_rs1en & (~(rv16_rs1idx == `E203_RFIDX_WIDTH'b0))); // 指令最终输出的译码结果,即改指令是否需要rs1、rs2、rd等操作数
assign dec_rs2en = rv32 ? rv32_need_rs2 : (rv16_rs2en & (~(rv16_rs2idx == `E203_RFIDX_WIDTH'b0)));
assign dec_rdwen = rv32 ? rv32_need_rd : (rv16_rden & (~(rv16_rdidx == `E203_RFIDX_WIDTH'b0)));
assign dec_rs1x0 = (dec_rs1idx == `E203_RFIDX_WIDTH'b0); //指令最终的译码结果,指令 rs1和rs2 是否是x0
assign dec_rs2x0 = (dec_rs2idx == `E203_RFIDX_WIDTH'b0);
wire rv_index_ilgl;
`ifdef E203_RFREG_NUM_IS_4 //{
assign rv_index_ilgl = // 判断rv_index是否合法,当reg file中的reg个数小于4时,如果解析出的指令的rs1、rs2、rd等的地址大于等于4
(| dec_rs1idx[`E203_RFIDX_WIDTH-1:2]) // 说明这个指令的地址不合法
|(| dec_rs2idx[`E203_RFIDX_WIDTH-1:2])
|(| dec_rdidx [`E203_RFIDX_WIDTH-1:2])
;
`endif//}
`ifdef E203_RFREG_NUM_IS_8 //{
assign rv_index_ilgl =
(| dec_rs1idx[`E203_RFIDX_WIDTH-1:3])
|(| dec_rs2idx[`E203_RFIDX_WIDTH-1:3])
|(| dec_rdidx [`E203_RFIDX_WIDTH-1:3])
;
`endif//}
`ifdef E203_RFREG_NUM_IS_16 //{
assign rv_index_ilgl =
(| dec_rs1idx[`E203_RFIDX_WIDTH-1:4])
|(| dec_rs2idx[`E203_RFIDX_WIDTH-1:4])
|(| dec_rdidx [`E203_RFIDX_WIDTH-1:4])
;
`endif//}
`ifdef E203_RFREG_NUM_IS_32 //{
//Never happen this illegal exception
assign rv_index_ilgl = 1'b0;
`endif//}
assign dec_rv32 = rv32; // 解析出的指令是否是32bit指令
assign dec_bjp_imm = // 解析出的跳转指令的立即数
({32{rv16_jal | rv16_j }} & rv16_jjal_imm)
| ({32{rv16_jalr_mv_add }} & rv16_jrjalr_imm)
| ({32{rv16_beqz | rv16_bnez }} & rv16_bxx_imm)
| ({32{rv32_jal }} & rv32_jal_imm)
| ({32{rv32_jalr }} & rv32_jalr_imm)
| ({32{rv32_branch }} & rv32_bxx_imm)
;
assign dec_jalr_rs1idx = rv32 ? rv32_rs1[`E203_RFIDX_WIDTH-1:0] : rv16_rs1[`E203_RFIDX_WIDTH-1:0]; // 解析出的jalr指令的rs1操作数的地址
assign dec_misalgn = i_misalgn;
assign dec_buserr = i_buserr ;
assign dec_ilegl = // 解析出的指令不合法
(rv_all0s1s_ilgl)
| (rv_index_ilgl)
| (rv16_addi16sp_ilgl)
| (rv16_addi4spn_ilgl)
| (rv16_li_lui_ilgl)
| (rv16_sxxi_shamt_ilgl)
| (rv32_sxxi_shamt_ilgl)
| (rv32_dret_ilgl)
| (rv16_lwsp_ilgl)
| (~legl_ops);
endmodule
整数通用寄存器组
//配合书本观看最好
`include "e203_defines.v"
module e203_exu_regfile(
input [`E203_RFIDX_WIDTH-1:0] read_src1_idx,
input [`E203_RFIDX_WIDTH-1:0] read_src2_idx,
output [`E203_XLEN-1:0] read_src1_dat,
output [`E203_XLEN-1:0] read_src2_dat,
input wbck_dest_wen,
input [`E203_RFIDX_WIDTH-1:0] wbck_dest_idx,
input [`E203_XLEN-1:0] wbck_dest_dat,
output [`E203_XLEN-1:0] x1_r,
input test_mode,
input clk,
input rst_n
);
wire [`E203_XLEN-1:0] rf_r [`E203_RFREG_NUM-1:0];
wire [`E203_RFREG_NUM-1:0] rf_wen;
`ifdef E203_REGFILE_LATCH_BASED //{
// Use DFF to buffer the write-port
wire [`E203_XLEN-1:0] wbck_dest_dat_r;
sirv_gnrl_dffl #(`E203_XLEN) wbck_dat_dffl (wbck_dest_wen, wbck_dest_dat, wbck_dest_dat_r, clk);
wire [`E203_RFREG_NUM-1:0] clk_rf_ltch;//buffer输出
`endif//}
genvar i;
generate //{
for (i=0; i<`E203_RFREG_NUM; i=i+1) begin:regfile//{
if(i==0) begin: rf0
// x0 cannot be wrote since it is constant-zeros
assign rf_wen[i] = 1'b0;//这里采取的是一个并行独热码选通
assign rf_r[i] = `E203_XLEN'b0;//数据是000000.....
`ifdef E203_REGFILE_LATCH_BASED //{
assign clk_rf_ltch[i] = 1'b0;//要是是基于latch的话还要再设置一拍,防止出现latch穿通效应
`endif//}
end
else begin: rfno0
assign rf_wen[i] = wbck_dest_wen & (wbck_dest_idx == i) ;
`ifdef E203_REGFILE_LATCH_BASED //{
e203_clkgate u_e203_clkgate(//时钟门控电路,降低功耗用的
.clk_in (clk ),
.test_mode(test_mode),
.clock_en(rf_wen[i]),
.clk_out (clk_rf_ltch[i])
);
//from write-enable to clk_rf_ltch to rf_ltch
sirv_gnrl_ltch #(`E203_XLEN) rf_ltch (clk_rf_ltch[i], wbck_dest_dat_r, rf_r[i]);
`else//}{
sirv_gnrl_dffl #(`E203_XLEN) rf_dffl (rf_wen[i], wbck_dest_dat, rf_r[i], clk);
`endif//}
end
end//}
endgenerate//}
assign read_src1_dat = rf_r[read_src1_idx];
assign read_src2_dat = rf_r[read_src2_idx];
// wire [`E203_XLEN-1:0] x0 = rf_r[0];
// wire [`E203_XLEN-1:0] x1 = rf_r[1];
// wire [`E203_XLEN-1:0] x2 = rf_r[2];
// wire [`E203_XLEN-1:0] x3 = rf_r[3];
// wire [`E203_XLEN-1:0] x4 = rf_r[4];
// wire [`E203_XLEN-1:0] x5 = rf_r[5];
// wire [`E203_XLEN-1:0] x6 = rf_r[6];
// wire [`E203_XLEN-1:0] x7 = rf_r[7];
// wire [`E203_XLEN-1:0] x8 = rf_r[8];
// wire [`E203_XLEN-1:0] x9 = rf_r[9];
// wire [`E203_XLEN-1:0] x10 = rf_r[10];
// wire [`E203_XLEN-1:0] x11 = rf_r[11];
// wire [`E203_XLEN-1:0] x12 = rf_r[12];
// wire [`E203_XLEN-1:0] x13 = rf_r[13];
// wire [`E203_XLEN-1:0] x14 = rf_r[14];
// wire [`E203_XLEN-1:0] x15 = rf_r[15];
// `ifdef E203_RFREG_NUM_IS_32 //{
// wire [`E203_XLEN-1:0] x16 = rf_r[16];
// wire [`E203_XLEN-1:0] x17 = rf_r[17];
// wire [`E203_XLEN-1:0] x18 = rf_r[18];
// wire [`E203_XLEN-1:0] x19 = rf_r[19];
// wire [`E203_XLEN-1:0] x20 = rf_r[20];
// wire [`E203_XLEN-1:0] x21 = rf_r[21];
// wire [`E203_XLEN-1:0] x22 = rf_r[22];
// wire [`E203_XLEN-1:0] x23 = rf_r[23];
// wire [`E203_XLEN-1:0] x24 = rf_r[24];
// wire [`E203_XLEN-1:0] x25 = rf_r[25];
// wire [`E203_XLEN-1:0] x26 = rf_r[26];
// wire [`E203_XLEN-1:0] x27 = rf_r[27];
// wire [`E203_XLEN-1:0] x28 = rf_r[28];
// wire [`E203_XLEN-1:0] x29 = rf_r[29];
// wire [`E203_XLEN-1:0] x30 = rf_r[30];
// wire [`E203_XLEN-1:0] x31 = rf_r[31];
// `endif//}
assign x1_r = rf_r[1];
endmodule
CSR模块
1.内存和存储器地址区间无关
2.CPU内部的寄存器
3.使用自己的编码空间
4.配置或记录一些运行的状态
module e203_exu_csr(
input nonflush_cmt_ena,
`ifdef E203_HAS_NICE
output nice_xs_off,
`endif
input csr_ena,
input csr_wr_en,
input csr_rd_en,
input [12-1:0] csr_idx,
output csr_access_ilgl,
output tm_stop,
output core_cgstop,
output tcm_cgstop,
output itcm_nohold,
output mdv_nob2b,
output [`E203_XLEN-1:0] read_csr_dat,
input [`E203_XLEN-1:0] wbck_csr_dat,
input [`E203_HART_ID_W-1:0] core_mhartid,
input ext_irq_r,
input sft_irq_r,
input tmr_irq_r,
output status_mie_r,
output mtie_r,
output msie_r,
output meie_r,
output wr_dcsr_ena ,
output wr_dpc_ena ,
output wr_dscratch_ena,
input [`E203_XLEN-1:0] dcsr_r ,
input [`E203_PC_SIZE-1:0] dpc_r ,
input [`E203_XLEN-1:0] dscratch_r,
output [`E203_XLEN-1:0] wr_csr_nxt ,
input dbg_mode,
input dbg_stopcycle,
output u_mode,
output s_mode,
output h_mode,
output m_mode,
input [`E203_ADDR_SIZE-1:0] cmt_badaddr,
input cmt_badaddr_ena,
input [`E203_PC_SIZE-1:0] cmt_epc,
input cmt_epc_ena,
input [`E203_XLEN-1:0] cmt_cause,
input cmt_cause_ena,
input cmt_status_ena,
input cmt_instret_ena,
input cmt_mret_ena,
output[`E203_PC_SIZE-1:0] csr_epc_r,
output[`E203_PC_SIZE-1:0] csr_dpc_r,
output[`E203_XLEN-1:0] csr_mtvec_r,
input clk_aon,
input clk,
input rst_n
);
assign csr_access_ilgl = 1'b0
;
// Only toggle when need to read or write to save power
wire wbck_csr_wen = csr_wr_en & csr_ena & (~csr_access_ilgl);
wire read_csr_ena = csr_rd_en & csr_ena & (~csr_access_ilgl);
wire [1:0] priv_mode = u_mode ? 2'b00 :
s_mode ? 2'b01 :
h_mode ? 2'b10 :
m_mode ? 2'b11 :
2'b11;
//0x000 URW ustatus User status register.
// * Since we support the user-level interrupt, hence we need to support UIE
//0x300 MRW mstatus Machine status register.
wire sel_ustatus = (csr_idx == 12'h000);
wire sel_mstatus = (csr_idx == 12'h300);
wire rd_ustatus = sel_ustatus & csr_rd_en;
wire rd_mstatus = sel_mstatus & csr_rd_en;
wire wr_ustatus = sel_ustatus & csr_wr_en;
wire wr_mstatus = sel_mstatus & csr_wr_en;
/
// Note: the below implementation only apply to Machine-mode config,
// if other mode is also supported, these logics need to be updated
//
// Implement MPIE field
//
wire status_mpie_r;
// The MPIE Feilds will be updates when:
wire status_mpie_ena =
// The CSR is written by CSR instructions
(wr_mstatus & wbck_csr_wen) |
// The MRET instruction commited
cmt_mret_ena |
// The Trap is taken
cmt_status_ena;
wire status_mpie_nxt =
// See Priv SPEC:
// When a trap is taken from privilege mode y into privilege
// mode x, xPIE is set to the value of xIE;
// So, When the Trap is taken, the MPIE is updated with the current MIE value
cmt_status_ena ? status_mie_r :
// See Priv SPEC:
// When executing an xRET instruction, supposing xPP holds the value y, xIE
// is set to xPIE; the privilege mode is changed to y;
// xPIE is set to 1;
// So, When the MRET instruction commited, the MPIE is updated with 1
cmt_mret_ena ? 1'b1 :
// When the CSR is written by CSR instructions
(wr_mstatus & wbck_csr_wen) ? wbck_csr_dat[7] : // MPIE is in field 7 of mstatus
status_mpie_r; // Unchanged
sirv_gnrl_dfflr #(1) status_mpie_dfflr (status_mpie_ena, status_mpie_nxt, status_mpie_r, clk, rst_n);
//
// Implement MIE field
//
// The MIE Feilds will be updates same as MPIE
wire status_mie_ena = status_mpie_ena;
wire status_mie_nxt =
// See Priv SPEC:
// When a trap is taken from privilege mode y into privilege
// mode x, xPIE is set to the value of xIE,
// xIE is set to 0;
// So, When the Trap is taken, the MIE is updated with 0
cmt_status_ena ? 1'b0 :
// See Priv SPEC:
// When executing an xRET instruction, supposing xPP holds the value y, xIE
// is set to xPIE; the privilege mode is changed to y, xPIE is set to 1;
// So, When the MRET instruction commited, the MIE is updated with MPIE
cmt_mret_ena ? status_mpie_r :
// When the CSR is written by CSR instructions
(wr_mstatus & wbck_csr_wen) ? wbck_csr_dat[3] : // MIE is in field 3 of mstatus
status_mie_r; // Unchanged
sirv_gnrl_dfflr #(1) status_mie_dfflr (status_mie_ena, status_mie_nxt, status_mie_r, clk, rst_n);
//
// Implement SD field
//
// See Priv SPEC:
// The SD bit is read-only
// And is set when either the FS or XS bits encode a Dirty
// state (i.e., SD=((FS==11) OR (XS==11))).
wire [1:0] status_fs_r;
wire [1:0] status_xs_r;
wire status_sd_r = (status_fs_r == 2'b11) | (status_xs_r == 2'b11);
assign status_xs_r = 2'b0;
//
// Implement XS field
//
// See Priv SPEC:
// XS field is read-only
// The XS field represents a summary of all extensions' status
// But in E200 we implement XS exactly same as FS to make it usable by software to
// disable extended accelerators
`ifdef E203_HAS_NICE
// If no NICE coprocessor interface configured, the XS is just hardwired to 0
assign nice_xs_off = 1'b0;// We just make this signal to 0
`endif
//
// Implement FS field
//
`ifndef E203_HAS_FPU
// If no FPU configured, the FS is just hardwired to 0
assign status_fs_r = 2'b0;
`endif
//
// Pack to the full mstatus register
//
wire [`E203_XLEN-1:0] status_r;
assign status_r[31] = status_sd_r; //SD
assign status_r[30:23] = 8'b0; // Reserved
assign status_r[22:17] = 6'b0; // TSR--MPRV
assign status_r[16:15] = status_xs_r; // XS
assign status_r[14:13] = status_fs_r; // FS
assign status_r[12:11] = 2'b11; // MPP
assign status_r[10:9] = 2'b0; // Reserved
assign status_r[8] = 1'b0; // SPP
assign status_r[7] = status_mpie_r; // MPIE
assign status_r[6] = 1'b0; // Reserved
assign status_r[5] = 1'b0; // SPIE
assign status_r[4] = 1'b0; // UPIE
assign status_r[3] = status_mie_r; // MIE
assign status_r[2] = 1'b0; // Reserved
assign status_r[1] = 1'b0; // SIE
assign status_r[0] = 1'b0; // UIE
wire [`E203_XLEN-1:0] csr_mstatus = status_r;
//0x004 URW uie User interrupt-enable register.
// * Since we dont delegate interrupt to user mode, hence it is as all 0s
//0x304 MRW mie Machine interrupt-enable register.
wire sel_mie = (csr_idx == 12'h304);
wire rd_mie = sel_mie & csr_rd_en;
wire wr_mie = sel_mie & csr_wr_en;
wire mie_ena = wr_mie & wbck_csr_wen;
wire [`E203_XLEN-1:0] mie_r;
wire [`E203_XLEN-1:0] mie_nxt;
assign mie_nxt[31:12] = 20'b0;
assign mie_nxt[11] = wbck_csr_dat[11];//MEIE
assign mie_nxt[10:8] = 3'b0;
assign mie_nxt[ 7] = wbck_csr_dat[ 7];//MTIE
assign mie_nxt[6:4] = 3'b0;
assign mie_nxt[ 3] = wbck_csr_dat[ 3];//MSIE
assign mie_nxt[2:0] = 3'b0;
sirv_gnrl_dfflr #(`E203_XLEN) mie_dfflr (mie_ena, mie_nxt, mie_r, clk, rst_n);
wire [`E203_XLEN-1:0] csr_mie = mie_r;
assign meie_r = csr_mie[11];
assign mtie_r = csr_mie[ 7];
assign msie_r = csr_mie[ 3];
//0x044 URW uip User interrupt pending.
// We dont support delegation scheme, so no need to support the uip
//0x344 MRW mip Machine interrupt pending
wire sel_mip = (csr_idx == 12'h344);
wire rd_mip = sel_mip & csr_rd_en;
//wire wr_mip = sel_mip & csr_wr_en;
// The MxIP is read-only
wire meip_r;
wire msip_r;
wire mtip_r;
sirv_gnrl_dffr #(1) meip_dffr (ext_irq_r, meip_r, clk, rst_n);
sirv_gnrl_dffr #(1) msip_dffr (sft_irq_r, msip_r, clk, rst_n);
sirv_gnrl_dffr #(1) mtip_dffr (tmr_irq_r, mtip_r, clk, rst_n);
wire [`E203_XLEN-1:0] ip_r;
assign ip_r[31:12] = 20'b0;
assign ip_r[11] = meip_r;
assign ip_r[10:8] = 3'b0;
assign ip_r[ 7] = mtip_r;
assign ip_r[6:4] = 3'b0;
assign ip_r[ 3] = msip_r;
assign ip_r[2:0] = 3'b0;
wire [`E203_XLEN-1:0] csr_mip = ip_r;
//
//0x005 .
// We dont support user trap, so no utvec needed
//0x305 MRW mtvec Machine trap-handler base address.
wire sel_mtvec = (csr_idx == 12'h305);
wire rd_mtvec = csr_rd_en & sel_mtvec;
`ifdef E203_SUPPORT_MTVEC //{
wire wr_mtvec = sel_mtvec & csr_wr_en;
wire mtvec_ena = (wr_mtvec & wbck_csr_wen);
wire [`E203_XLEN-1:0] mtvec_r;
wire [`E203_XLEN-1:0] mtvec_nxt = wbck_csr_dat;
sirv_gnrl_dfflr #(`E203_XLEN) mtvec_dfflr (mtvec_ena, mtvec_nxt, mtvec_r, clk, rst_n);
wire [`E203_XLEN-1:0] csr_mtvec = mtvec_r;
`else//}{
// THe vector table base is a configurable parameter, so we dont support writeable to it
wire [`E203_XLEN-1:0] csr_mtvec = `E203_MTVEC_TRAP_BASE;
`endif//}
assign csr_mtvec_r = csr_mtvec;
//0x340 MRW mscratch
wire sel_mscratch = (csr_idx == 12'h340);
wire rd_mscratch = sel_mscratch & csr_rd_en;
`ifdef E203_SUPPORT_MSCRATCH //{
wire wr_mscratch = sel_mscratch & csr_wr_en;
wire mscratch_ena = (wr_mscratch & wbck_csr_wen);
wire [`E203_XLEN-1:0] mscratch_r;
wire [`E203_XLEN-1:0] mscratch_nxt = wbck_csr_dat;
sirv_gnrl_dfflr #(`E203_XLEN) mscratch_dfflr (mscratch_ena, mscratch_nxt, mscratch_r, clk, rst_n);
wire [`E203_XLEN-1:0] csr_mscratch = mscratch_r;
`else//}{
wire [`E203_XLEN-1:0] csr_mscratch = `E203_XLEN'b0;
`endif//}
// 0xB00 MRW mcycle
// 0xB02 MRW minstret
// 0xB80 MRW mcycleh
// 0xB82 MRW minstreth
wire sel_mcycle = (csr_idx == 12'hB00);
wire sel_mcycleh = (csr_idx == 12'hB80);
wire sel_minstret = (csr_idx == 12'hB02);
wire sel_minstreth = (csr_idx == 12'hB82);
// 0xBFF MRW counterstop
// This register is our self-defined register to stop
// the cycle/time/instret counters to save dynamic powers
wire sel_counterstop = (csr_idx == 12'hBFF);// This address is not used by ISA
// 0xBFE MRW mcgstop
// This register is our self-defined register to disable the
// automaticall clock gating for CPU logics for debugging purpose
wire sel_mcgstop = (csr_idx == 12'hBFE);// This address is not used by ISA
// 0xBFD MRW itcmnohold
// This register is our self-defined register to disble the
// ITCM SRAM output holdup feature, if set, then we assume
// ITCM SRAM output cannot holdup last read value
wire sel_itcmnohold = (csr_idx == 12'hBFD);// This address is not used by ISA
// 0xBF0 MRW mdvnob2b
// This register is our self-defined register to disble the
// Mul/div back2back feature
wire sel_mdvnob2b = (csr_idx == 12'hBF0);// This address is not used by ISA
wire rd_mcycle = csr_rd_en & sel_mcycle ;
wire rd_mcycleh = csr_rd_en & sel_mcycleh ;
wire rd_minstret = csr_rd_en & sel_minstret ;
wire rd_minstreth = csr_rd_en & sel_minstreth;
wire rd_itcmnohold = csr_rd_en & sel_itcmnohold;
wire rd_mdvnob2b = csr_rd_en & sel_mdvnob2b;
wire rd_counterstop = csr_rd_en & sel_counterstop;
wire rd_mcgstop = csr_rd_en & sel_mcgstop;
`ifdef E203_SUPPORT_MCYCLE_MINSTRET //{
wire wr_mcycle = csr_wr_en & sel_mcycle ;
wire wr_mcycleh = csr_wr_en & sel_mcycleh ;
wire wr_minstret = csr_wr_en & sel_minstret ;
wire wr_minstreth = csr_wr_en & sel_minstreth;
wire wr_itcmnohold = csr_wr_en & sel_itcmnohold ;
wire wr_mdvnob2b = csr_wr_en & sel_mdvnob2b ;
wire wr_counterstop = csr_wr_en & sel_counterstop;
wire wr_mcgstop = csr_wr_en & sel_mcgstop ;
wire mcycle_wr_ena = (wr_mcycle & wbck_csr_wen);
wire mcycleh_wr_ena = (wr_mcycleh & wbck_csr_wen);
wire minstret_wr_ena = (wr_minstret & wbck_csr_wen);
wire minstreth_wr_ena = (wr_minstreth & wbck_csr_wen);
wire itcmnohold_wr_ena = (wr_itcmnohold & wbck_csr_wen);
wire mdvnob2b_wr_ena = (wr_mdvnob2b & wbck_csr_wen);
wire counterstop_wr_ena = (wr_counterstop & wbck_csr_wen);
wire mcgstop_wr_ena = (wr_mcgstop & wbck_csr_wen);
wire [`E203_XLEN-1:0] mcycle_r ;
wire [`E203_XLEN-1:0] mcycleh_r ;
wire [`E203_XLEN-1:0] minstret_r ;
wire [`E203_XLEN-1:0] minstreth_r;
wire cy_stop;
wire ir_stop;
wire stop_cycle_in_dbg = dbg_stopcycle & dbg_mode;
wire mcycle_ena = mcycle_wr_ena |
((~cy_stop) & (~stop_cycle_in_dbg) & (1'b1));
wire mcycleh_ena = mcycleh_wr_ena |
((~cy_stop) & (~stop_cycle_in_dbg) & ((mcycle_r == (~(`E203_XLEN'b0)))));
wire minstret_ena = minstret_wr_ena |
((~ir_stop) & (~stop_cycle_in_dbg) & (cmt_instret_ena));
wire minstreth_ena = minstreth_wr_ena |
((~ir_stop) & (~stop_cycle_in_dbg) & ((cmt_instret_ena & (minstret_r == (~(`E203_XLEN'b0))))));
wire [`E203_XLEN-1:0] mcycle_nxt = mcycle_wr_ena ? wbck_csr_dat : (mcycle_r + 1'b1);
wire [`E203_XLEN-1:0] mcycleh_nxt = mcycleh_wr_ena ? wbck_csr_dat : (mcycleh_r + 1'b1);
wire [`E203_XLEN-1:0] minstret_nxt = minstret_wr_ena ? wbck_csr_dat : (minstret_r + 1'b1);
wire [`E203_XLEN-1:0] minstreth_nxt = minstreth_wr_ena ? wbck_csr_dat : (minstreth_r + 1'b1);
//We need to use the always-on clock for this counter
sirv_gnrl_dfflr #(`E203_XLEN) mcycle_dfflr (mcycle_ena, mcycle_nxt, mcycle_r , clk_aon, rst_n);
sirv_gnrl_dfflr #(`E203_XLEN) mcycleh_dfflr (mcycleh_ena, mcycleh_nxt, mcycleh_r , clk_aon, rst_n);
sirv_gnrl_dfflr #(`E203_XLEN) minstret_dfflr (minstret_ena, minstret_nxt, minstret_r , clk, rst_n);
sirv_gnrl_dfflr #(`E203_XLEN) minstreth_dfflr (minstreth_ena, minstreth_nxt, minstreth_r, clk, rst_n);
wire [`E203_XLEN-1:0] counterstop_r;
wire counterstop_ena = counterstop_wr_ena;
wire [`E203_XLEN-1:0] counterstop_nxt = {29'b0,wbck_csr_dat[2:0]};// Only LSB 3bits are useful
sirv_gnrl_dfflr #(`E203_XLEN) counterstop_dfflr (counterstop_ena, counterstop_nxt, counterstop_r, clk, rst_n);
wire [`E203_XLEN-1:0] csr_mcycle = mcycle_r;
wire [`E203_XLEN-1:0] csr_mcycleh = mcycleh_r;
wire [`E203_XLEN-1:0] csr_minstret = minstret_r;
wire [`E203_XLEN-1:0] csr_minstreth = minstreth_r;
wire [`E203_XLEN-1:0] csr_counterstop = counterstop_r;
`else//}{
wire [`E203_XLEN-1:0] csr_mcycle = `E203_XLEN'b0;
wire [`E203_XLEN-1:0] csr_mcycleh = `E203_XLEN'b0;
wire [`E203_XLEN-1:0] csr_minstret = `E203_XLEN'b0;
wire [`E203_XLEN-1:0] csr_minstreth = `E203_XLEN'b0;
wire [`E203_XLEN-1:0] csr_counterstop = `E203_XLEN'b0;
`endif//}
wire [`E203_XLEN-1:0] itcmnohold_r;
wire itcmnohold_ena = itcmnohold_wr_ena;
wire [`E203_XLEN-1:0] itcmnohold_nxt = {31'b0,wbck_csr_dat[0]};// Only LSB 1bits are useful
sirv_gnrl_dfflr #(`E203_XLEN) itcmnohold_dfflr (itcmnohold_ena, itcmnohold_nxt, itcmnohold_r, clk, rst_n);
wire [`E203_XLEN-1:0] csr_itcmnohold = itcmnohold_r;
wire [`E203_XLEN-1:0] mdvnob2b_r;
wire mdvnob2b_ena = mdvnob2b_wr_ena;
wire [`E203_XLEN-1:0] mdvnob2b_nxt = {31'b0,wbck_csr_dat[0]};// Only LSB 1bits are useful
sirv_gnrl_dfflr #(`E203_XLEN) mdvnob2b_dfflr (mdvnob2b_ena, mdvnob2b_nxt, mdvnob2b_r, clk, rst_n);
wire [`E203_XLEN-1:0] csr_mdvnob2b = mdvnob2b_r;
assign cy_stop = counterstop_r[0];// Stop CYCLE counter
assign tm_stop = counterstop_r[1];// Stop TIME counter
assign ir_stop = counterstop_r[2];// Stop INSTRET counter
assign itcm_nohold = itcmnohold_r[0];// ITCM no-hold up feature
assign mdv_nob2b = mdvnob2b_r[0];// Mul/Div no back2back feature
wire [`E203_XLEN-1:0] mcgstop_r;
wire mcgstop_ena = mcgstop_wr_ena;
wire [`E203_XLEN-1:0] mcgstop_nxt = {30'b0,wbck_csr_dat[1:0]};// Only LSB 2bits are useful
sirv_gnrl_dfflr #(`E203_XLEN) mcgstop_dfflr (mcgstop_ena, mcgstop_nxt, mcgstop_r, clk, rst_n);
wire [`E203_XLEN-1:0] csr_mcgstop = mcgstop_r;
assign core_cgstop = mcgstop_r[0];// Stop Core clock gating
assign tcm_cgstop = mcgstop_r[1];// Stop TCM clock gating
//`ifdef E203_SUPPORT_CYCLE //{
0xC00 URO cycle
0xC80 URO cycleh
//wire sel_cycle = (csr_idx == 12'hc00);
//wire sel_cycleh = (csr_idx == 12'hc80);
//wire rd_cycle = sel_cycle & csr_rd_en;
//wire wr_cycle = sel_cycle & csr_wr_en;
//wire cycle_ena = (wr_cycle & wbck_csr_wen);
//wire rd_cycleh = sel_cycleh & csr_rd_en;
//wire wr_cycleh = sel_cycleh & csr_wr_en;
//wire cycleh_ena = (wr_cycleh & wbck_csr_wen);
//wire [`E203_XLEN-1:0] cycle_r;
//wire [`E203_XLEN-1:0] cycleh_r;
//wire [`E203_XLEN-1:0] cycle_nxt = wbck_csr_dat;
//wire [`E203_XLEN-1:0] cycleh_nxt = wbck_csr_dat;
//sirv_gnrl_dfflr #(`E203_XLEN) cycle_dfflr (cycle_ena, cycle_nxt, cycle_r, clk, rst_n);
//sirv_gnrl_dfflr #(`E203_XLEN) cycleh_dfflr(cycleh_ena,cycleh_nxt,cycleh_r,clk, rst_n);
//wire [`E203_XLEN-1:0] csr_cycle = cycle_r;
//wire [`E203_XLEN-1:0] csr_cycleh = cycleh_r;
//`else//}{
//wire [`E203_XLEN-1:0] csr_cycle = `E203_XLEN'b0;
//wire [`E203_XLEN-1:0] csr_cycleh = `E203_XLEN'b0;
//`endif//}
//
//0x041 URW uepc User exception program counter.
// We dont support user trap, so no uepc needed
//0x341 MRW mepc Machine exception program counter.
wire sel_mepc = (csr_idx == 12'h341);
wire rd_mepc = sel_mepc & csr_rd_en;
wire wr_mepc = sel_mepc & csr_wr_en;
wire epc_ena = (wr_mepc & wbck_csr_wen) | cmt_epc_ena;
wire [`E203_PC_SIZE-1:0] epc_r;
wire [`E203_PC_SIZE-1:0] epc_nxt;
assign epc_nxt[`E203_PC_SIZE-1:1] = cmt_epc_ena ? cmt_epc[`E203_PC_SIZE-1:1] : wbck_csr_dat[`E203_PC_SIZE-1:1];
assign epc_nxt[0] = 1'b0;// Must not hold PC which will generate the misalign exception according to ISA
sirv_gnrl_dfflr #(`E203_PC_SIZE) epc_dfflr (epc_ena, epc_nxt, epc_r, clk, rst_n);
wire [`E203_XLEN-1:0] csr_mepc;
wire dummy_0;
assign {dummy_0,csr_mepc} = {{`E203_XLEN+1-`E203_PC_SIZE{1'b0}},epc_r};
assign csr_epc_r = csr_mepc;
//0x042 URW ucause User trap cause.
// We dont support user trap, so no ucause needed
//0x342 MRW mcause Machine trap cause.
wire sel_mcause = (csr_idx == 12'h342);
wire rd_mcause = sel_mcause & csr_rd_en;
wire wr_mcause = sel_mcause & csr_wr_en;
wire cause_ena = (wr_mcause & wbck_csr_wen) | cmt_cause_ena;
wire [`E203_XLEN-1:0] cause_r;
wire [`E203_XLEN-1:0] cause_nxt;
assign cause_nxt[31] = cmt_cause_ena ? cmt_cause[31] : wbck_csr_dat[31];
assign cause_nxt[30:4] = 27'b0;
assign cause_nxt[3:0] = cmt_cause_ena ? cmt_cause[3:0] : wbck_csr_dat[3:0];
sirv_gnrl_dfflr #(`E203_XLEN) cause_dfflr (cause_ena, cause_nxt, cause_r, clk, rst_n);
wire [`E203_XLEN-1:0] csr_mcause = cause_r;
//0x043 URW ubadaddr User bad address.
// We dont support user trap, so no ubadaddr needed
//0x343 MRW mbadaddr Machine bad address.
wire sel_mbadaddr = (csr_idx == 12'h343);
wire rd_mbadaddr = sel_mbadaddr & csr_rd_en;
wire wr_mbadaddr = sel_mbadaddr & csr_wr_en;
wire cmt_trap_badaddr_ena = cmt_badaddr_ena;
wire badaddr_ena = (wr_mbadaddr & wbck_csr_wen) | cmt_trap_badaddr_ena;
wire [`E203_ADDR_SIZE-1:0] badaddr_r;
wire [`E203_ADDR_SIZE-1:0] badaddr_nxt;
assign badaddr_nxt = cmt_trap_badaddr_ena ? cmt_badaddr : wbck_csr_dat[`E203_ADDR_SIZE-1:0];
sirv_gnrl_dfflr #(`E203_ADDR_SIZE) badaddr_dfflr (badaddr_ena, badaddr_nxt, badaddr_r, clk, rst_n);
wire [`E203_XLEN-1:0] csr_mbadaddr;
wire dummy_1;
assign {dummy_1,csr_mbadaddr} = {{`E203_XLEN+1-`E203_ADDR_SIZE{1'b0}},badaddr_r};
// We dont support the delegation scheme, so no need to implement
// delegete registers
//0x301 MRW misa ISA and extensions
wire sel_misa = (csr_idx == 12'h301);
wire rd_misa = sel_misa & csr_rd_en;
// Only implemented the M mode, IMC or EMC
wire [`E203_XLEN-1:0] csr_misa = {
2'b1
,4'b0 //WIRI
,1'b0 // 25 Z Reserved
,1'b0 // 24 Y Reserved
,1'b0 // 23 X Non-standard extensions present
,1'b0 // 22 W Reserved
,1'b0 // 21 V Tentatively reserved for Vector extension 20 U User mode implemented
,1'b0 // 20 U User mode implemented
,1'b0 // 19 T Tentatively reserved for Transactional Memory extension
,1'b0 // 18 S Supervisor mode implemented
,1'b0 // 17 R Reserved
,1'b0 // 16 Q Quad-precision floating-point extension
,1'b0 // 15 P Tentatively reserved for Packed-SIMD extension
,1'b0 // 14 O Reserved
,1'b0 // 13 N User-level interrupts supported
,1'b1 // 12 M Integer Multiply/Divide extension
,1'b0 // 11 L Tentatively reserved for Decimal Floating-Point extension
,1'b0 // 10 K Reserved
,1'b0 // 9 J Reserved
`ifdef E203_RFREG_NUM_IS_32
,1'b1 // 8 I RV32I/64I/128I base ISA
`else
,1'b0
`endif
,1'b0 // 7 H Hypervisor mode implemented
,1'b0 // 6 G Additional standard extensions present
`ifndef E203_HAS_FPU//{
,1'b0 // 5 F Single-precision floating-point extension
`endif//
`ifdef E203_RFREG_NUM_IS_32
,1'b0 // 4 E RV32E base ISA
`else
,1'b1 //
`endif
`ifndef E203_HAS_FPU//{
,1'b0 // 3 D Double-precision floating-point extension
`endif//
,1'b1 // 2 C Compressed extension
,1'b0 // 1 B Tentatively reserved for Bit operations extension
`ifdef E203_SUPPORT_AMO//{
,1'b1 // 0 A Atomic extension
`endif//E203_SUPPORT_AMO}
`ifndef E203_SUPPORT_AMO//{
,1'b0 // 0 A Atomic extension
`endif//}
};
//Machine Information Registers
//0xF11 MRO mvendorid Vendor ID.
//0xF12 MRO marchid Architecture ID.
//0xF13 MRO mimpid Implementation ID.
//0xF14 MRO mhartid Hardware thread ID.
wire [`E203_XLEN-1:0] csr_mvendorid = `E203_XLEN'h536;
wire [`E203_XLEN-1:0] csr_marchid = `E203_XLEN'hE203;
wire [`E203_XLEN-1:0] csr_mimpid = `E203_XLEN'h1;
wire [`E203_XLEN-1:0] csr_mhartid = {{`E203_XLEN-`E203_HART_ID_W{1'b0}},core_mhartid};
wire rd_mvendorid = csr_rd_en & (csr_idx == 12'hF11);
wire rd_marchid = csr_rd_en & (csr_idx == 12'hF12);
wire rd_mimpid = csr_rd_en & (csr_idx == 12'hF13);
wire rd_mhartid = csr_rd_en & (csr_idx == 12'hF14);
//0x7b0 Debug Control and Status
//0x7b1 Debug PC
//0x7b2 Debug Scratch Register
//0x7a0 Trigger selection register
wire sel_dcsr = (csr_idx == 12'h7b0);
wire sel_dpc = (csr_idx == 12'h7b1);
wire sel_dscratch = (csr_idx == 12'h7b2);
wire rd_dcsr = dbg_mode & csr_rd_en & sel_dcsr ;
wire rd_dpc = dbg_mode & csr_rd_en & sel_dpc ;
wire rd_dscratch = dbg_mode & csr_rd_en & sel_dscratch;
assign wr_dcsr_ena = dbg_mode & csr_wr_en & sel_dcsr ;
assign wr_dpc_ena = dbg_mode & csr_wr_en & sel_dpc ;
assign wr_dscratch_ena = dbg_mode & csr_wr_en & sel_dscratch;
assign wr_csr_nxt = wbck_csr_dat;
wire [`E203_XLEN-1:0] csr_dcsr = dcsr_r ;
`ifdef E203_PC_SIZE_IS_16
wire [`E203_XLEN-1:0] csr_dpc = {{`E203_XLEN-`E203_PC_SIZE{1'b0}},dpc_r};
`endif
`ifdef E203_PC_SIZE_IS_24
wire [`E203_XLEN-1:0] csr_dpc = {{`E203_XLEN-`E203_PC_SIZE{1'b0}},dpc_r};
`endif
`ifdef E203_PC_SIZE_IS_32
wire [`E203_XLEN-1:0] csr_dpc = dpc_r ;
`endif
wire [`E203_XLEN-1:0] csr_dscratch = dscratch_r;
assign csr_dpc_r = dpc_r;
/
// Generate the Read path
//Currently we only support the M mode to simplify the implementation and
// reduce the gatecount because we are a privite core
assign u_mode = 1'b0;
assign s_mode = 1'b0;
assign h_mode = 1'b0;
assign m_mode = 1'b1;
assign read_csr_dat = `E203_XLEN'b0
//| ({`E203_XLEN{rd_ustatus }} & csr_ustatus )
| ({`E203_XLEN{rd_mstatus }} & csr_mstatus )
| ({`E203_XLEN{rd_mie }} & csr_mie )
| ({`E203_XLEN{rd_mtvec }} & csr_mtvec )
| ({`E203_XLEN{rd_mepc }} & csr_mepc )
| ({`E203_XLEN{rd_mscratch }} & csr_mscratch )
| ({`E203_XLEN{rd_mcause }} & csr_mcause )
| ({`E203_XLEN{rd_mbadaddr }} & csr_mbadaddr )
| ({`E203_XLEN{rd_mip }} & csr_mip )
| ({`E203_XLEN{rd_misa }} & csr_misa )
| ({`E203_XLEN{rd_mvendorid}} & csr_mvendorid)
| ({`E203_XLEN{rd_marchid }} & csr_marchid )
| ({`E203_XLEN{rd_mimpid }} & csr_mimpid )
| ({`E203_XLEN{rd_mhartid }} & csr_mhartid )
| ({`E203_XLEN{rd_mcycle }} & csr_mcycle )
| ({`E203_XLEN{rd_mcycleh }} & csr_mcycleh )
| ({`E203_XLEN{rd_minstret }} & csr_minstret )
| ({`E203_XLEN{rd_minstreth}} & csr_minstreth)
| ({`E203_XLEN{rd_counterstop}} & csr_counterstop)// Self-defined
| ({`E203_XLEN{rd_mcgstop}} & csr_mcgstop)// Self-defined
| ({`E203_XLEN{rd_itcmnohold}} & csr_itcmnohold)// Self-defined
| ({`E203_XLEN{rd_mdvnob2b}} & csr_mdvnob2b)// Self-defined
| ({`E203_XLEN{rd_dcsr }} & csr_dcsr )
| ({`E203_XLEN{rd_dpc }} & csr_dpc )
| ({`E203_XLEN{rd_dscratch }} & csr_dscratch)
;
endmodule
指令发射和派遣
E203采用两级流水线架构,所以派遣和发射表示一个概念,就是给ALU执行
这里统一用派遣,派遣功能由派遣模块和ALU一起完成
`include "e203_defines.v"
module e203_exu_disp(
input wfi_halt_exu_req,
output wfi_halt_exu_ack,
input oitf_empty,
input amo_wait,
//
// The operands and decode info from dispatch
input disp_i_valid, // Handshake valid
output disp_i_ready, // Handshake ready
// The operand 1/2 read-enable signals and indexes
input disp_i_rs1x0,
input disp_i_rs2x0,
input disp_i_rs1en,
input disp_i_rs2en,
input [`E203_RFIDX_WIDTH-1:0] disp_i_rs1idx,
input [`E203_RFIDX_WIDTH-1:0] disp_i_rs2idx,
input [`E203_XLEN-1:0] disp_i_rs1,
input [`E203_XLEN-1:0] disp_i_rs2,
input disp_i_rdwen,
input [`E203_RFIDX_WIDTH-1:0] disp_i_rdidx,
input [`E203_DECINFO_WIDTH-1:0] disp_i_info,
input [`E203_XLEN-1:0] disp_i_imm,
input [`E203_PC_SIZE-1:0] disp_i_pc,
input disp_i_misalgn,
input disp_i_buserr ,
input disp_i_ilegl ,
//
// Dispatch to ALU
output disp_o_alu_valid,
input disp_o_alu_ready,
input disp_o_alu_longpipe,
output [`E203_XLEN-1:0] disp_o_alu_rs1,
output [`E203_XLEN-1:0] disp_o_alu_rs2,
output disp_o_alu_rdwen,
output [`E203_RFIDX_WIDTH-1:0] disp_o_alu_rdidx,
output [`E203_DECINFO_WIDTH-1:0] disp_o_alu_info,
output [`E203_XLEN-1:0] disp_o_alu_imm,
output [`E203_PC_SIZE-1:0] disp_o_alu_pc,
output [`E203_ITAG_WIDTH-1:0] disp_o_alu_itag,
output disp_o_alu_misalgn,
output disp_o_alu_buserr ,
output disp_o_alu_ilegl ,
//
// Dispatch to OITF
input oitfrd_match_disprs1,
input oitfrd_match_disprs2,
input oitfrd_match_disprs3,
input oitfrd_match_disprd,
input [`E203_ITAG_WIDTH-1:0] disp_oitf_ptr ,
output disp_oitf_ena,
input disp_oitf_ready,
output disp_oitf_rs1fpu,
output disp_oitf_rs2fpu,
output disp_oitf_rs3fpu,
output disp_oitf_rdfpu ,
output disp_oitf_rs1en ,
output disp_oitf_rs2en ,
output disp_oitf_rs3en ,
output disp_oitf_rdwen ,
output [`E203_RFIDX_WIDTH-1:0] disp_oitf_rs1idx,
output [`E203_RFIDX_WIDTH-1:0] disp_oitf_rs2idx,
output [`E203_RFIDX_WIDTH-1:0] disp_oitf_rs3idx,
output [`E203_RFIDX_WIDTH-1:0] disp_oitf_rdidx ,
output [`E203_PC_SIZE-1:0] disp_oitf_pc ,
input clk,
input rst_n
);
wire [`E203_DECINFO_GRP_WIDTH-1:0] disp_i_info_grp = disp_i_info [`E203_DECINFO_GRP];
// Based on current 2 pipe stage implementation, the 2nd stage need to have all instruction
// to be commited via ALU interface, so every instruction need to be dispatched to ALU,
// regardless it is long pipe or not, and inside ALU it will issue instructions to different
// other longpipes
//wire disp_alu = (disp_i_info_grp == `E203_DECINFO_GRP_ALU)
// | (disp_i_info_grp == `E203_DECINFO_GRP_BJP)
// | (disp_i_info_grp == `E203_DECINFO_GRP_CSR)
// `ifdef E203_SUPPORT_SHARE_MULDIV //{
// | (disp_i_info_grp == `E203_DECINFO_GRP_MULDIV)
// `endif//E203_SUPPORT_SHARE_MULDIV}
// | (disp_i_info_grp == `E203_DECINFO_GRP_AGU);
wire disp_csr = (disp_i_info_grp == `E203_DECINFO_GRP_CSR);
wire disp_alu_longp_prdt = (disp_i_info_grp == `E203_DECINFO_GRP_AGU)
;
wire disp_alu_longp_real = disp_o_alu_longpipe;
// Both fence and fencei need to make sure all outstanding instruction have been completed
wire disp_fence_fencei = (disp_i_info_grp == `E203_DECINFO_GRP_BJP) &
( disp_i_info [`E203_DECINFO_BJP_FENCE] | disp_i_info [`E203_DECINFO_BJP_FENCEI]);
// Since any instruction will need to be dispatched to ALU, we dont need the gate here
// wire disp_i_ready_pos = disp_alu & disp_o_alu_ready;
// assign disp_o_alu_valid = disp_alu & disp_i_valid_pos;
wire disp_i_valid_pos;
wire disp_i_ready_pos = disp_o_alu_ready;
assign disp_o_alu_valid = disp_i_valid_pos;
//
// The Dispatch Scheme Introduction for two-pipeline stage
// #1: The instruction after dispatched must have already have operand fetched, so
// there is no any WAR dependency happened.
// #2: The ALU-instruction are dispatched and executed in-order inside ALU, so
// there is no any WAW dependency happened among ALU instructions.
// Note: LSU since its AGU is handled inside ALU, so it is treated as a ALU instruction
// #3: The non-ALU-instruction are all tracked by OITF, and must be write-back in-order, so
// it is like ALU in-ordered. So there is no any WAW dependency happened among
// non-ALU instructions.
// Then what dependency will we have?
// * RAW: This is the real dependency
// * WAW: The WAW between ALU an non-ALU instructions
//
// So #1, The dispatching ALU instruction can not proceed and must be stalled when
// ** RAW: The ALU reading operands have data dependency with OITF entries
// *** Note: since it is 2 pipeline stage, any last ALU instruction have already
// write-back into the regfile. So there is no chance for ALU instr to depend
// on last ALU instructions as RAW.
// Note: if it is 3 pipeline stages, then we also need to consider the ALU-to-ALU
// RAW dependency.
// ** WAW: The ALU writing result have no any data dependency with OITF entries
// Note: Since the ALU instruction handled by ALU may surpass non-ALU OITF instructions
// so we must check this.
// And #2, The dispatching non-ALU instruction can not proceed and must be stalled when
// ** RAW: The non-ALU reading operands have data dependency with OITF entries
// *** Note: since it is 2 pipeline stage, any last ALU instruction have already
// write-back into the regfile. So there is no chance for non-ALU instr to depend
// on last ALU instructions as RAW.
// Note: if it is 3 pipeline stages, then we also need to consider the non-ALU-to-ALU
// RAW dependency.
wire raw_dep = ((oitfrd_match_disprs1) |
(oitfrd_match_disprs2) |
(oitfrd_match_disprs3));
// Only check the longp instructions (non-ALU) for WAW, here if we
// use the precise version (disp_alu_longp_real), it will hurt timing very much, but
// if we use imprecise version of disp_alu_longp_prdt, it is kind of tricky and in
// some corner case. For example, the AGU (treated as longp) will actually not dispatch
// to longp but just directly commited, then it become a normal ALU instruction, and should
// check the WAW dependency, but this only happened when it is AMO or unaligned-uop, so
// ideally we dont need to worry about it, because
// * We dont support AMO in 2 stage CPU here
// * We dont support Unalign load-store in 2 stage CPU here, which
// will be triggered as exception, so will not really write-back
// into regfile
// * But it depends on some assumption, so it is still risky if in the future something changed.
// Nevertheless: using this condition only waiver the longpipe WAW case, that is, two
// longp instruction write-back same reg back2back. Is it possible or is it common?
// after we checking the benmark result we found if we remove this complexity here
// it just does not change any benchmark number, so just remove that condition out. Means
// all of the instructions will check waw_dep
//wire alu_waw_dep = (~disp_alu_longp_prdt) & (oitfrd_match_disprd & disp_i_rdwen);
wire waw_dep = (oitfrd_match_disprd);
wire dep = raw_dep | waw_dep;
// The WFI halt exu ack will be asserted when the OITF is empty
// and also there is no AMO oustanding uops
assign wfi_halt_exu_ack = oitf_empty & (~amo_wait);
wire disp_condition =
// To be more conservtive, any accessing CSR instruction need to wait the oitf to be empty.
// Theoretically speaking, it should also flush pipeline after the CSR have been updated
// to make sure the subsequent instruction get correct CSR values, but in our 2-pipeline stage
// implementation, CSR is updated after EXU stage, and subsequent are all executed at EXU stage,
// no chance to got wrong CSR values, so we dont need to worry about this.
(disp_csr ? oitf_empty : 1'b1)
// To handle the Fence: just stall dispatch until the OITF is empty
& (disp_fence_fencei ? oitf_empty : 1'b1)
// If it was a WFI instruction commited halt req, then it will stall the disaptch
& (~wfi_halt_exu_req)
// No dependency
& (~dep)
// If dispatch to ALU as long pipeline, then must check
// the OITF is ready
& ((disp_alu & disp_o_alu_longpipe) ? disp_oitf_ready : 1'b1);
// To cut the critical timing path from longpipe signal
// we always assume the LSU will need oitf ready
& (disp_alu_longp_prdt ? disp_oitf_ready : 1'b1);
assign disp_i_valid_pos = disp_condition & disp_i_valid;
assign disp_i_ready = disp_condition & disp_i_ready_pos;
wire [`E203_XLEN-1:0] disp_i_rs1_msked = disp_i_rs1 & {`E203_XLEN{~disp_i_rs1x0}};
wire [`E203_XLEN-1:0] disp_i_rs2_msked = disp_i_rs2 & {`E203_XLEN{~disp_i_rs2x0}};
// Since we always dispatch any instructions into ALU, so we dont need to gate ops here
//assign disp_o_alu_rs1 = {`E203_XLEN{disp_alu}} & disp_i_rs1_msked;
//assign disp_o_alu_rs2 = {`E203_XLEN{disp_alu}} & disp_i_rs2_msked;
//assign disp_o_alu_rdwen = disp_alu & disp_i_rdwen;
//assign disp_o_alu_rdidx = {`E203_RFIDX_WIDTH{disp_alu}} & disp_i_rdidx;
//assign disp_o_alu_info = {`E203_DECINFO_WIDTH{disp_alu}} & disp_i_info;
assign disp_o_alu_rs1 = disp_i_rs1_msked;
assign disp_o_alu_rs2 = disp_i_rs2_msked;
assign disp_o_alu_rdwen = disp_i_rdwen;
assign disp_o_alu_rdidx = disp_i_rdidx;
assign disp_o_alu_info = disp_i_info;
// Why we use precise version of disp_longp here, because
// only when it is really dispatched as long pipe then allocate the OITF
assign disp_oitf_ena = disp_o_alu_valid & disp_o_alu_ready & disp_alu_longp_real;
assign disp_o_alu_imm = disp_i_imm;
assign disp_o_alu_pc = disp_i_pc;
assign disp_o_alu_itag = disp_oitf_ptr;
assign disp_o_alu_misalgn= disp_i_misalgn;
assign disp_o_alu_buserr = disp_i_buserr ;
assign disp_o_alu_ilegl = disp_i_ilegl ;
`ifndef E203_HAS_FPU//{
wire disp_i_fpu = 1'b0;
wire disp_i_fpu_rs1en = 1'b0;
wire disp_i_fpu_rs2en = 1'b0;
wire disp_i_fpu_rs3en = 1'b0;
wire disp_i_fpu_rdwen = 1'b0;
wire [`E203_RFIDX_WIDTH-1:0] disp_i_fpu_rs1idx = `E203_RFIDX_WIDTH'b0;
wire [`E203_RFIDX_WIDTH-1:0] disp_i_fpu_rs2idx = `E203_RFIDX_WIDTH'b0;
wire [`E203_RFIDX_WIDTH-1:0] disp_i_fpu_rs3idx = `E203_RFIDX_WIDTH'b0;
wire [`E203_RFIDX_WIDTH-1:0] disp_i_fpu_rdidx = `E203_RFIDX_WIDTH'b0;
wire disp_i_fpu_rs1fpu = 1'b0;
wire disp_i_fpu_rs2fpu = 1'b0;
wire disp_i_fpu_rs3fpu = 1'b0;
wire disp_i_fpu_rdfpu = 1'b0;
`endif//}
assign disp_oitf_rs1fpu = disp_i_fpu ? (disp_i_fpu_rs1en & disp_i_fpu_rs1fpu) : 1'b0;
assign disp_oitf_rs2fpu = disp_i_fpu ? (disp_i_fpu_rs2en & disp_i_fpu_rs2fpu) : 1'b0;
assign disp_oitf_rs3fpu = disp_i_fpu ? (disp_i_fpu_rs3en & disp_i_fpu_rs3fpu) : 1'b0;
assign disp_oitf_rdfpu = disp_i_fpu ? (disp_i_fpu_rdwen & disp_i_fpu_rdfpu ) : 1'b0;
assign disp_oitf_rs1en = disp_i_fpu ? disp_i_fpu_rs1en : disp_i_rs1en;
assign disp_oitf_rs2en = disp_i_fpu ? disp_i_fpu_rs2en : disp_i_rs2en;
assign disp_oitf_rs3en = disp_i_fpu ? disp_i_fpu_rs3en : 1'b0;
assign disp_oitf_rdwen = disp_i_fpu ? disp_i_fpu_rdwen : disp_i_rdwen;
assign disp_oitf_rs1idx = disp_i_fpu ? disp_i_fpu_rs1idx : disp_i_rs1idx;
assign disp_oitf_rs2idx = disp_i_fpu ? disp_i_fpu_rs2idx : disp_i_rs2idx;
assign disp_oitf_rs3idx = disp_i_fpu ? disp_i_fpu_rs3idx : `E203_RFIDX_WIDTH'b0;
assign disp_oitf_rdidx = disp_i_fpu ? disp_i_fpu_rdidx : disp_i_rdidx;
assign disp_oitf_pc = disp_i_pc;
endmodule
流水线冲突、长指令、OITF
1.资源冲突
2.数据冲突
关键词解析:
握手信号
时钟门控
多路复用MUX