本次课上指令 withdraw
的功能是撤销上一次的 sw
操作, 比较复杂,但构思好结构便可事半功倍。下面是题目要求
# CP0 的修改
在 中,新增 4 个 32 位寄存器:
- $18 :
IM_HI
,撤回地址的上界,可通过mfc0
和mtc0
进行读写 - $19 :
IM_LO
,撤回地址的下界,可通过mfc0
和mtc0
进行读写 - $20 :
LastAddr
,储存上一次sw
所存的地址,可通过mfc0
读取 - $21 :
LastData
,储存上一次sw
所存的数据,可通过mfc0
读取
每当 sw
指令执行时,需要在 的 20、21 号寄存器中写入相应数据
# RTL 描述
withdraw<br>000001 | code |
---|---|
6 | 26 |
if(CP0[20]>=CP0[18] && CP0[20]<CP0[19]):
memory[CP0[20]] ← CP0[21]
else:
SignalException(AdES)
# 注意
withdraw
也是一种访存指令,在执行时,字节使能信号与sw
相同CP0 内的 20、21 号寄存器不会被 mtc0 写入,如果出现了与其相关的 mtc0 指令,CPU 将不会执行任何操作,忽略即可
初始时 CP0 内四个寄存器均为 0,如果出现了
withdraw
指令,CPU 不会进行任何操作,忽略即可评测数据保证了每次执行
withdraw
时,IM_HI
和IM_LO
的合法性:上界大于下界,且地址均 4 对齐
以上便是题面的精简版。
根据笔者自身经历和与其他同学的交流,本题大致有两种思路
将新指令的实现主体置于 CP0 中
这是一上来容易想到的思路,因为与新指令有关的寄存器都在 CP0 中,在 CP0 中处理该指令理所当然。但是这就无法与其他访存指令统一,在笔者看来比较麻烦,不符合 CPU 的结构。并且笔者所了解到的未通过此题的同学,都采用了这种思路。
将新指令的实现主体至于 BE 中,与其他访存指令相统一
这也是笔者的思路。将 CP0 中四个寄存器所存的值引到 BE 模块中,而 BE 模块只需要根据新增的
withdraw
指令修改多路选择器即可。结构清晰,实现简单。