# P3 课上测试游记
通过阅读本文,您可以大致了解 2021 年秋季北航计算机组成课程 P3 课上测试的题目内容、难度和解题思路
P3 课上测试的主要内容是对课下用 Logisim 搭建单周期 CPU 进行强测,同时添加一些新指令
题目每年都会发生变化,题意描述大致清晰,但是可能与原题有一定差异
想要完成 P3 课上,请务必保证熟悉单周期 CPU 的数据通路,同时课下一定要尝试自行添加一些指令,比如
jal
和jr
以及lb
和sb
# T1 添加 bezal
指令
指令的意思是 branch if equal to zero and link
指令格式
special | $rs | $rt | 0 | 0 | funct |
---|---|---|---|---|---|
000000 | 5 位寄存器地址 | 5 位寄存器地址 | 00000 | 00000 | 110001 |
操作
if (GPR[$rt] == 0)
NPC <- GPR[$rs]
GPR[$ra] <- PC + 4
else
NPC <- PC + 4
解法
- ALU 增加一位输出,判断
$rt
是否为 0,把这一位连到 NPC 和 CTRL 上 - GRF 读出的 RD1 连到 NPC 上(如果课下搭过
jr
,那这一步已经做过了) - NPC 根据信号判断是否跳转到
GPR[$rs]
- CTRL 根据信号判断 GPR 的写使能
WE
是否为 1(即是否把PC + 4
写到$ra
里面)(这一条我刚开始没加,就意味着每一次执行到bezal
,不管是否相等,都会往$ra
里面写入PC+4
,但是自己测试根本看不出,调了 20+min...)
# T2 添加 slo
指令
指令的意思是 shift left and or
这一题出的就比较灵活了
指令格式
special | 0 | $rt | $rd | shamt | funct |
---|---|---|---|---|---|
000000 | 00000 | 5 位寄存器地址 | 5 位寄存器地址 | 左移的位数 | 101010 |
操作
GPR[$rd] <- GPR[$rd]<<shamt | 1*{shamt}
(翻译成大白话)把 $rt
里的值左移 shamt
位,左移出来的位填 1,把这个数存到 $rd
解法
- 首先明确只需要在 ALU 和 CTRL 中修改
- 下面是非常暴力的做法
- 首先利用 Bit Shifter 把
GPR[$rd]
左移shamt
位 - 然后再利用 Bit Shifter 把
32'b1000_0000_0000_0000_0000_0000_0000_0000
算术右移shamt-1
位 - 再把上述结果利用 Bit Shifter 循环左移
shamt
位 - 得到了
32'b0000...00111...1
(后面有shamt
个 1) - 然后两者取按位或运算得到答案
# T3 添加 lwor
指令
指令的意思就是是 load word
指令格式
opcode | base | $rt | offset |
---|---|---|---|
101101 | 5 位寄存器地址 | 5 位寄存器地址 | 16 位偏移量 |
操作
Addr <- [GPR[base] + sign_extend(offset) + rt*4] & 0x7c
GPR[rt] <- Memory[Addr]
注意区分 rt
和 $rt
,前者代表 rt
的地址,后者代表 GPR($rt)
解法
- 首先明确需要修改的是 ALU 和 CTRL(注意,其实本题不需要对 DM 做任何改动)
- 把操作中描述的那一堆运算扔给 ALU 做,输出 C 就连接 DM 的地址
- 注意再做
rt*4
的时候先扩展到 32 位再移位,否则可能会溢出?
# T4 选择题
第一题是挑错,找 beq
和 jal
实现中的错误,位扩展、与门和或门用错了
第二题是问 subiu
和 addiu
是否等价,貌似补码表示时负数比正数能多表示一个数,所以我选的不等价对了,但是不知道是不是这个原因
# 提答
- 就是解释你的设计,然后问一下调试时的问题
# 一些提示
课上第一题前几个点好像只有课下添加的指令,如果这些错了也许是意味着课下的设计有问题,可能还要调试一会...