先试最简单的,第一个pipeline加在ID和EX之间。
之前的程序是controller和datapath分开的,流水线寄存器加在这代码上最好处理。
但现在不问题是datapath里包含pcreg和regfile。pcreg应该是在IF阶段,没有IF也应该在ID
里。
pcreg并没有经过流水线寄存器,如图上红线。虽然pcreg在datapath模块里,但实际上可以把它看
做在第一段流水线里,因为它的下一阶段instr是在流水线寄存器里了。但pcreg并不能和datapath
模块里不其它内容同步,+4是没问题的,但其它pcnextbr,pcnext都要首先等instr的内容,然后再读寄存器,接着还要再EX阶段里用ALU做下运算后才能确定。
比如测试例子里第一句指令就是一个beq或者jump,可以看到pcnext是得不出值的,所以还是
pcplus4,所以这时候就要用到stalll,等待后面EX段的结果。
0: 00000663 beq x0 x0 12 <test>
4: 00a00093 addi x1 x0 10
8: 00108093 addi x1 x1 1
0000000c <test>:
c: 00000533 add x10 x0 x0
That's the first cycle after reset. The first instruction is beq x0, x0, 0xc. It's a determined branch. You can see that the instr is still empty because it's in the second stage pipeline. pcnext is +4.
In the second clock cycle.
The pipeline register already read in the second instruction (00a00093)addi x1, x0, 10 which should never be executed. This instruction will be executed.
突然理解里MIPS里为什么在跳转语句后面有个slot,这个位置上的语句不受前面跳转语句不影响,无论怎样都会执行,应该就是这种情况吧。这样不需要刷流水线,虽然看上去搞个slot和别扭。
Now, dp.instr is 00000663, it's the bne. This is the first instruction that just be executed, at the second clock. So the pcnext updated to 0x10, which is incorrect. It should be 0xc.
跳转的位置不对,多了4.应该是和第二条指令读进流水线寄存器有关,pc又加了4.
这就体现出MIPS的鸡贼了。比如beq x0,x0,imm 这种。在RISC-V里, pcnextbr=pc+imm。
在MIPS里,pcnextbr=pc+4+imm。
第三个时钟周期,也就是执行不第二条指令就是这条slot上的4: 00a00093 addi x1 x0 10
可以从上图看到,x1被写入10了。(真正的写入在下一时钟的上升沿。没做下降沿写寄存器,因为
这样regfile里flipflop就要翻倍了,还不懂,好像网上的实现是这样。)
再确认一条指令,x1里值已经是10了,这条指令把x1+1, 11已经进来了
----------------------------------------------------------------------------------------------------------
pcreg放这个位置很不便于理解,后面要把它移出datapath。
现在controller,decoder放在第一段流水线里了,但regfile放到第二段流水线。后面也要把
regfile放到ID段来,因为在ID段里访问寄存器据说是开销很大的部分。