# P4 课上测试
通过阅读本文,您可以大致了解 2021 年秋季北航计算机组成课程 P4 课上测试的题目内容、难度和解题思路
P4 课上测试的主要内容是对课下用 Verilog 搭建的单周期 CPU 进行强测,同时添加一些新指令
题目每年都会发生变化,题意描述可能与原题有一定差异
想要完成 P4 课上,请务必保证熟悉单周期 CPU 的数据通路,同时课下一定要尝试自行添加一些指令,另外写设计文档时把 P3 时 Logisim 搭的 CPU 的图截一份放上去,这样添加指令的时候会非常清楚需要改变什么数据通路
课下强烈建议添加 lb
和 sb
,此外可以试一试 bltzal
指令,跟课上的跳转非常类似,而且 Mars 里面有现成的,总之课上测试的跳转一般是 branch and link
感觉今年 P4 课上像是娱乐局,但是我很菜所以竞速失败了
不说了,放题目
# T1 添加 RLB
指令
指令描述
31:26 | 25:21 | 20:16 | 15:0 |
---|---|---|---|
111111 | $rs 地址 | $rt 地址 | 16 位立即数 imm |
指令格式
rlb rt, rs, imm
RTL 语言描述
if imm == 0 then
GPR[$rt] <- GPR[$rs]
else
GPR[$rt] <- $rs[31:imm] || inverse($rs[(imm-1):0])
endif
注:这里的 inverse
是按位取反的意思
一句话描述: GPR[$rs]
的低 imm
位按位取反,存入 GPR[$rt]
中
解法
- 首先明确这是一个运算指令,只需要修改
ALU
即可 ALUOp
添加信号ALU_rlb
,用for
循环把低imm
位按位取反,剩下位原样放到ALU
的输出C
中
//imm 会放到 B 里,题面保证 imm 在 0~31 之间,因此 imm 可以符号扩展也可以无符号扩展 | |
for(i=0; i<B; i=i+1) C[i] = !A[i]; | |
for(i=B; i<32; i=i+1) C[i] = A[i] |
对,关键代码就这么长...
- 其它的就是普通的运算指令了
# T2 添加 BNEZALC
指令
这一题如果你课下加过
bltzal
,那就是大水题直接过
指令描述
31:26(regimm) | 25:21 | 20:16 | 15:0 |
---|---|---|---|
000001 | $rs 地址 | 10011 | offset |
指令格式
bnezalc rs, offset
RTL 语言描述
if GPR[$rs] != 0 then
PC <- PC + 4 + sign_extend(offset||2'b00)
GPR[$31] <- PC + 4
else
PC <- PC + 4
endif
一句话描述:如果 GPR[$rs] != GPR[$rt]
那么跳转并链接到 $31
,否则顺序执行但是不链接
解法
首先明确这是一个跳转指令,对于我的设计而言,只需要修改
CMP
即可CMP
直接加一下不等就把jump
置为 1 即可注意
CTRL
中GRFWrEn
即寄存器的写使能信号要添加一个| !(bnezalc && !jump)
,即不跳转不链接其他的和
beq
是相同的,直接写就好
# T3 添加 LWRR
指令
这一题和去年的
swrr
神似...
指令描述
31:26 | 25:21 | 20:16 | 15:0 |
---|---|---|---|
110100 | base | $rt 地址 | offset |
指令格式
lwrr rt, offset(base)
RTL 语言描述
vAddr <- GPR[base] + sign_extend(offset)
memw <- Memory[vAddr]
byte <- vAddr[1:0]
if byte == 0 then
GPR[$rt] <- Memory[vAddr]
else
GPR[$rt] <- Memory[vAddr][8*byte-1 : 0] || Memory[vAddr][31 : 8*byte]
endif
没有一句话描述,直接看 RTL 语言
解法
- 首先明确这是一个访存指令,对于我的设计而言,只需要修改
DM
即可 - 修改
DM
的输出逻辑使得符合题意
assign RD = ...(忽略) | |
(DMOp == `DM_lwrr & byte == 2'b00) : mem[Addr[11:2]] ? | |
(DMOp == `DM_lwrr & byte == 2'b01) : {mem[Addr[11:2]][7:0], mem[Addr[11:2]][31:8]} ? | |
(DMOp == `DM_lwrr & byte == 2'b10) : {mem[Addr[11:2]][15:0], mem[Addr[11:2]][31:16]} ? | |
(DMOp == `DM_lwrr & byte == 2'b11) : {mem[Addr[11:2]][23:0], mem[Addr[11:2]][31:24]} ? | |
mem[Addr[11:2]]; |
关键代码如上
- 其他的和
lw
是相同的,直接写就好
# 选择与提答
- 选择考察
NPC
的写法,就是看熟不熟悉指令集,可以打开指令集对着仔细看看就行 - 助教没问多少问题,
也许是交的早的原因吧,看了看设计文档和代码就没了