P5课上测试#
一.增添指令一般步骤#
- 明确指令RTL,可以使用课上提供的.class文件进行模拟
- 明确非转发数据通路:可以在单周期中思考新指令的行为,构思出数据通路
- 考虑转发:
- 考虑GRF的五位写入地址是否正确,一般在第二步已经调整完毕,但是像lwer,lhso等条件存储类指令只有在M级中从DM中取出数据后才能明确写入地址,需要在M级将写入地址再次修改
- 明确新指令的T_rs_use,T_rt_use,T_new,用不到的寄存器设置为T_rs/rt_use = 3
二.课上测试题型分析#
1.计算指令——在E级就可以完成所有操作#
新增的计算指令一般只需要增加ALU的功能,但是计算行为会稍稍复杂一些,Tnew和Tuse与calc_R或calc_I型保持一致即可
例如 循环左移
1
2
| if(B[4:0] == 5'b0) out = A;
else out = A << B[4:0] | A >> (6'd32 - B[4:0])
|
2.条件跳转类——在D级就可以完成所有操作#
- 条件跳转 + 无条件链接
- 条件跳转 + 条件链接
- 条件跳转 + 条件(无条件)链接 + 不跳转时清空延迟槽
1.条件跳转#
2.无条件链接#
- D级将RegWrite置为1,跟随流水并更改A3(31),最后在W级选择PC8作为写入数据
3.条件链接#
- 在D级根据CMP模块的输出结果判断RegWrite是否有效
- 设置一个check信号用以确定当前指令是否为新指令,进行流水
1
2
3
4
5
6
7
| wire D_RegWrite_new = check_D ? (D_CMP_out ? 1'b1 : 1'b0) : RegWrite_D;
//判断是否为新信号 如果是就已经隐含着regwrite=1,只需对CMP结果进行判断
//如果不是就保留原信号
//uut
E_reg top_e_reg(
.RegWrite_D(D_RegWrite_new),
);
|
4.不跳转时清空延迟槽#
- 根据CMP输出结果判断是否要清空D级流水寄存器(这就是hyggge学长P5教程中D级clr信号接口的原因
QAQ) - 注意:当前为stall状态则不能清空延迟槽,此时传入CMP模块的不是新值,判断无效
1
2
3
4
5
| wire D_reg_clr = check_D & ~D_CMP_out & ~stall //新信号 & 不跳转 & 不暂停
D_reg top_d_reg(
.D_clr(D_reg_clr) //加入到同步复位列表中
);
|
3.条件存储类——在M级就可以完成所有操作#
- 在原来基础上修改stall控制信号,如果D级的指令要读寄存器,而且后面的新指令可能要写这个寄存器,那么就stall
- 修改写入A3地址并传入W_reg和HCU
1. condition1#
- condition成立 :将DM中值写入A
- condition不成立 :将DM中值写入B
1
2
3
4
5
6
7
8
9
10
11
12
13
14
| //第一种题型(eg:condition满足向rt号写,否则写31号)
assign stall_rs_E = (D_A1 != 5'd0) & (check_E ? (D_A1 == E_A3 | D_A1 == 5'd31) : D_A1 == E_A3) & (RFWrite_E) & (Tuse_rs < Tnew_E);
assign stall_rs_M = (D_A1 != 5'd0) & (check_M ? (D_A1 == M_A3 | D_A1 == 5'd31) : D_A1 == M_A3) & (RFWrite_M) & (Tuse_rs < Tnew_M);
assign stall_rt_E = (D_A2 != 5'd0) & (check_E ? (D_A2 == E_A3 | D_A2 == 5'd31) : D_A2 == E_A3) & (RFWrite_E) & (Tuse_rt < Tnew_E);
assign stall_rt_M = (D_A2 != 5'd0) & (check_M ? (D_A2 == M_A3 | D_A2 == 5'd31) : D_A2 == M_A3) & (RFWrite_M) & (Tuse_rt < Tnew_M);
//更改写入寄存器地址(eg:condition满足向rt号写,否则写31号)
wire M_A3_new = check_M ? (condition ? `rt : 5'd31) : M_A3;
//uut
W_reg top_w_reg(
.M_A3(M_A3_new),
);
HCU top_hcu(
.M_A3(M_A3_new),
);
|
2.condition2#
- conditon成立 :向31号写
- condition不成立 :不写(写入0号寄存器)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
| //按照第一种题型以写成 (check_M ? (D_A2 == 5'd31 | D_A2 == 5'd0): D_A2 == M_A3),因为前面有条件 D_A2 != 5'd0,所以可以简化
assign stall_rs_E = (D_A1 != 5'd0) & (check_E ? D_A2 == 5'd31 : D_A2 == M_A3) & (RFWrite_E) & (Tuse_rs < Tnew_E);
assign stall_rs_M = (D_A1 != 5'd0) & (check_M ? D_A2 == 5'd31 : D_A2 == M_A3) & (RFWrite_M) & (Tuse_rs < Tnew_M);
assign stall_rt_E = (D_A2 != 5'd0) & (check_E ? D_A2 == 5'd31 : D_A2 == M_A3) & (RFWrite_E) & (Tuse_rt < Tnew_E);
assign stall_rt_M = (D_A2 != 5'd0) & (check_M ? D_A2 == 5'd31 : D_A2 == M_A3) & (RFWrite_M) & (Tuse_rt < Tnew_M);
//更改写入寄存器地址(eg:condition满足向31号写,否则不写)
wire M_A3_new = check_M ? (condition ? 5'd31 : 5'd0) : M_A3;
//uut
W_reg top_w_reg(
.M_A3(M_A3_new),
);
HCU top_hcu(
.M_A3(M_A3_new),
);
|
3.condition3#
- condition满足时写入DM中值的低五位
- 这种情况下可能写入所有的寄存器,直接暂停
1
2
3
4
5
6
7
8
9
10
11
12
13
14
| //第三种题型 (eg:condition满足时写入位置为DM的读取值的低五位)
assign stall_rs_E = (D_A1 != 5'd0) & (check_E ? 1'b1 : D_A2 == M_A3) & (RFWrite_E) & (Tuse_rs < Tnew_E);
assign stall_rs_M = (D_A1 != 5'd0) & (check_M ? 1'b1 : D_A2 == M_A3) & (RFWrite_M) & (Tuse_rs < Tnew_M);
assign stall_rt_E = (D_A2 != 5'd0) & (check_E ? 1'b1 : D_A2 == M_A3) & (RFWrite_E) & (Tuse_rt < Tnew_E);
assign stall_rt_M = (D_A2 != 5'd0) & (check_M ? 1'b1 : D_A2 == M_A3) & (RFWrite_M) & (Tuse_rt < Tnew_M);
//更改写入寄存器地址(eg:写入位置为DM的读取值的低五位)
wire M_A3_new = check_M ? DM_out[4:0] : M_A3;
//uut
W_reg top_w_reg(
.M_A3(M_A3_new),
);
HCU top_hcu(
.M_A3(M_A3_new),
);
|