cs61c 构建数据通路(risc)
寄存器一直输出,但是只有在上升沿,他才会改变输出的结果。(此时要求we也必须为1)
寄存器文件,regwn说明可写。
rs1和rs2都是索引,索引我们真正写入的对象。
rd和rsw是一个东西。当regwen是1且clk是1的时候。我们可以写入寄存器文件。初次之外的任何时间,我们都在读取数据。
这是mem,我们可以看到他有addr和dataw。以及datar。对于写的时候,要求设置clk为上升沿,然后memrw为1.addr是实际上我们要写的地址。然后dataw是数据。但是注意addr既是写入又是读取地址。一样只有上升沿且memrw为1时充当写的角色。对于imem,我们永远不会设置memrw为0,所以他们相当于这两种等价。
想象成同一个内存空间,然后两个线,分别当做两种mem。
选择应为哪一种,rs2或者immediate,注意immediate是一个扩展的32位的立即数,参考是addi还是add
其中load不是其他类型的指令,而恰好是i类型指令,因此所有字段均可以在相同位置使用。
我们的dmem以及我们的mux,新的mux选择写回寄存器的值。
如果是add指令,我们写alu,但是如果是load指令,我们写回的应该是dmem中读取的数据了。
而且如果是loadi指令的话,我们还需要一个imm,因为load是i指令,只要看到i指令,我们的通路就会去产生信号产生imm
imm这个立即数以及从寄存器文件中读取到的寄存器rs1中的数据进行加法操作,得到的结果中读取dmem中数据,然后如果是add指令我们走mux上边,但我们是load指令,所以我们会读取dmem。
所有的load指令在这里。这是第一个使用了全部五个流程的。
store指令是store到mem中,因此目标是mem。store的地址是rs1和imm(扩展后)的值的相加。
rs2是我们要写回的mem的地址。
我们没有一读一写,而是执行了两次读,读的内容分别是rs1+offset和rs2
由于这是s幸格式。区别就是我们的imm位置改变了。
只要我们的immsel选择为s,那么就会处理s型数据了。
有了一个额外的电线,选择rs2,目的是得到我们要写入的地址。此时我们不要alu,直接进入mem。然后根据memrw,我们选择了write,这样我们就可以确定我们是写入数据了,记住dmem是根据memrw来确定此时是读还是写得。
使用R(rs1)和imm相加得到地址,然后从R(rs2)得到数据,然后将数据写入对应地址并设置相关的控制指令。但是store不会更写我们的寄存器文件,他只是写入内存而已。因为我们设置了regwen为0,所以这也保证了无论数据是什么,都不会写回reg寄存器文件的。
如果是branch的文件,我们可以看到,我们得选择pc是pc加imm还是pc+4.
在下一个操作到来之前,每个组合逻辑块只能做一个操作。虽然alu可以进行分支操作,但是我们还要一个多余的alu操作。但我们只有一个alu,所以最后我们选择了使用一个branch模块进行操作
他通过比较R(rs1)和R(rs2)的值来选择结果。
我们的结果最终会变成control中的一个部分。
这个组合快接受brun以及两个数据,决定如何比较(有无符号)以及比较哪些,
以branch less than为例,我们使用brun,以及pcSel,然后发现r(rs1)<r(rs2),然后令brlt=1,breq=0;pcsel = taken
现在我们可以看到多了两条线,其中一条是选择我们要用pc还是rs1的值,以及pc最后要是用什么更新。
这一切都是在更新时产生的。
我们将memroy和处理器画成这个样子
数据是管道,而控制就是提线木偶
最开始是clk上升了,叮叮盯开始工作
现在是我们解码指令,同时我们pc+4,但是此时因为我们还没有到下一个上升沿,所以mux中pc+4处于等待状态。因为imm是一个只读设备,所以他此时处于读的状态,且不用时钟控制,读取除了数据,然后immsel决定了我们是什么类型的立即数,然后pcsel此时还在等待。然后是我们要不要写寄存器(regwen)。同时因为我们是sw指令,所以我们不关心reg是否是写的,我们关心的是mem,而且我们不会有branch的比较。几乎每个操作都要alu,这里我们将寄存器和立即数相加。我们可以看到bsel和asel的变化。
store几乎是唯一一个用到了memrw的。
为*表示他们根部不重要,我们不会写回寄存器,我们也根本不会关心分支。然后随着clock上升,我们写dmem,同时pc选择自己为pc+4
实际上唯一的三个更换是pc的更新,reg的更新和dmem的更新。
当时branch的时候,我们不会写reg的
但是我们会关心我们的写的内容,我们会将pc和brach的偏移量相加。我们并不写回内存。除了store基本上都只是读mem。因为是beq,所以我们只关心相等时,此时,我们的breq会对我们的pcsel产生影响,导致最后我们要了解我们的pc
现在是写寄存器,我们将immsel设置为*,将regwen设置为1,表示要写,然后将pcSel设置为0,
不关心比较,但关心比较结果的数据流通。
memrw是read,如果是write,那就不太好了,你会将add的结果和r2进行比较,emm,真实十分有趣呢。
这就是整体的流程了。
如果我不能立刻马上将alu进行加速,那么在下一个cock的上升沿之前,我就不太可能得到alu的计算结果,那么这个过程就变得没有意义了。所以bang,这就是个炸弹。在关键时刻到了,他现在就是正确的值。
clk-q来自启动这个上升沿的pc,然后绿色和黄色就是二选一的max,alu,mux
唯一的不同是一个在进入imm的时候,一个进入了reg,所以这两个的时间长的有决定性。