假设汇编代码在具有 5 级流水线的 32 位 MIPS 处理器上执行,支持停止但不转发。分支指令的比较是在执行阶段完成的。没有分支延迟槽。计算从 foo 标签后的 addi 指令的取指周期开始,到(包括)jr 指令的取指周期结束的时钟周期数。
.data .align 2 numbers: .space 40 .align 2 .text start: la $a0, numbers addi $a1, $0, 10 jal foo foo: addi $sp, $sp, -4 sw $a0, 0($sp) loop: sw $a1, 0($a0) addi $a0, $a0, 4 addi $a1, $a1, -1 bne $a1, $0, loop lw $t3, 0($sp) addi $sp, $sp, 4 lw $t0, 0($t3) lw $t1, 4($t3) add $v0, $t0, $t1 jr $ra
根据数据和控制危险,我计算了错过的周期数,总共 52 个周期。我还知道第一条指令
addi $sp, $sp, -4
需要 5 个周期才能完成,但之后我可以为每条指令再添加 1 个周期。排除第一条指令后,执行的指令总数为 47。然后我做了:5 + 47 = 52。因此,如果没有危险,只需要 52 个周期,但我们知道存在周期延迟,因此:
总周期 = 52 + 52 = 104
根据解决方案,我对错过的周期部分是正确的,但他们添加了 48,而不是 52。因此,“正确”答案是 96 个周期。但这是错误的,因为即使没有危险,程序也需要超过 48 个周期才能执行!
涉及此代码的另一个问题是它是否会终止,它会终止,但他们在解决方案表中另有说明。
.text
start:
la $a0, numbers
addi $a1, $0, 10
jal foo
# -- error, missing exit code: after jal foo,
# foo will run again by accident
foo:
addi $sp, $sp, -4 # 1 -- error should be addiu for pointer arithmetic
sw $a0, 0($sp) # 1+2 stalls on $sp
loop:
sw $a1, 0($a0) # 1 (10x)
addi $a0, $a0, 4 # 1 (10x) -- should be addiu
addi $a1, $a1, -1 # 1 (10x)
bne $a1, $0, loop # 1+2+2 (2 stalls on $a1, and taken branch) 9x
# 1+2+2 for last iteration 1x
lw $t3, 0($sp) # 1
addi $sp, $sp, 4 # 1 -- error should be addiu
lw $t0, 0($t3) # 1+1 stall on $t3
lw $t1, 4($t3) # 1
add $v0, $t0, $t1 # 1+2 stalls
# 1 for $t0 and 2 for $t1
# but they overlap, so max(1,2)
jr $ra # 1+2 (taken branch)
自己 | RAW档 | 分店摊位 | 仪器。总和 | 迭代次数 | 总金额 | 指导 |
---|---|---|---|---|---|---|
1 | 1 | 1 | 1 | 阿迪 | ||
1 | 2 | 3 | 1 | 3 | sw | |
1 | 1 | 10 | 10 | sw | ||
1 | 1 | 10 | 10 | 阿迪 | ||
1 | 1 | 10 | 10 | 阿迪 | ||
1 | 2 | 2 | 5 | 9 | 45 | 已采取bne |
1 | 2 | 2 | 5 | 1 | 5 | 未采取bne |
1 | 1 | 1 | 1 | lw | ||
1 | 1 | 1 | 1 | 阿迪 | ||
1 | 1 | 2 | 1 | 2 | lw | |
1 | 1 | 1 | 1 | lw | ||
1 | 2 | 3 | 1 | 3 | 阿迪 | |
1 | 2 | 3 | 1 | 3 | jr | |
48 | 95 |
我快95了;我不知道如何到达 96,但也许有人可以找到错误?