P7-CPU设计文档
本文最后更新于 2024年12月3日 中午
P7 debug总结
阻塞转发错误
上机的过程中遇到了转发错误,再三排查后,发现是mtc0产生了不应该有的转发.
在ID的控制模块CTRL中,我采用了一种过于"取巧"的方法,将rd写入了ID_A3(解码阶段输出的写入寄存器地址(向后传递直至WB阶段))
1 | |
这个ID_A3会随着流水线向后传递,并传递给HAZARD_CTRL(冒险控制模块)中用于处理阻塞和转发的问题.例如:
1 | |
那么问题来了,我的阻塞逻辑代码中,
1 | |
这样看似没有问题.但其实这里mtc0指令导入的A3并不是真正用于写入寄存器堆的地址,而是CP0的对应地址.因此有可能产生本不应该有的转发.例如以下代码
1 | |
该代码中,第二行指令mtc0错误地向add指令转发了$12的值,但它们指向的$12根本不是同一个寄存器!
我的对应措施是取消执行mtc0指令时rd写入ID_A3的做法,在HARZARD_CTRL中,传入MEM_instr和EX_instr(MEM,EX区当前各自传递的指令)
1 | |
中断错误
错误情况:
1 | |
这个bug在课上并没有发现,喜提计组"再来一次"大奖
首先说错误点:
**在发生阻塞时,ID和EX间的流水寄存器接收到冲洗信号,但应当保留PC和BD(branch
delay)*两种信息的传递,也就是按正常传递的逻辑传递PC和BD**
前者PC比较好理解,课下思考题也有问到这个问题.为了保证macroscopic_pc不出现诸如0x0000_0000这类的值.
但是BD稍微有些理解的困难度.当外部中断信号产生时,CP0会根据接受到BD来决定EPC存储的值,如果BD有误,那么PC跳转错误就很有可能发生,
1 | |
我验证了多种ID,EX间流水寄存器处理阻塞的错误方法,例如
1 | |
1 | |
1 | |
我们来看官方tb中的中断逻辑处理代码:
1 | |
用文字简述该逻辑:当macroscopic_pc到达tb指定的target_pc时,interupt置为1,即外部产生中断信号.
所以我们可以很容易的排除C:
当延迟槽指令位于ID区时,与流水线后面的指令发生阻塞冲突时(这种例子确实不太好列举):
1
2
3
4
5
6
7
8
9ori $20, 0x1001 # 3000
mtc0 $20, $12 // 允许中断 # 3004
ori $1, $0, 0x1234 # 3008
ori $2, $0, 0x2345 # 300c
mult $1, $2 # 3010
jal 0x3020 # 3014
mflo $3 # 3018(发生中断)
ori $5, $0, 0x5555 # 301c
ori $6, $0, 0x6666 # 3020
我们指定target_pc为0x3018,mflo会与EX区的MDU模块产生的busy信号发生冲突,因此在C情况下,ID和EX间的流水寄存器产生了nop指令,该指令携带着0x3018的PC和0的BD,传递到MEM区时,PC传递给macroscopic_pc输出到外界,触发了外界中断信号的产生,CP0接受到该中断信号进入中断处理逻辑,这时该模块依据接受到的BD处理EPC,但是BD是错误的,也就最终导致了跳转错误.
至于A和B,上述代码确实无法证明它的错误,我猜测是课上测试tb会有更复杂的中断信号产生的逻辑,总之,EX_PC <= ID_PC;EX_BD <= ID_BD;确实是最好的,因为它保证了两点:
- 发生阻塞的指令对应
PC会多次出现在macroscopic_pc中(A,B无法做到这一点) - 指令传递中,
PC一定与正确的BD对应