目前只完成了设计概念和硬件描述,支持部分常用32位MIPS指令(ADD, SUB, LW, SW等)。硬件描述用的是SystemVerilog语言,生成软件Synplify 9.6.2。昨天我测试了执行单元和指令控制单元,这两个主要的组件没大问题,剩下的不敢保证。别抱太大期望,大一计算机工程学生能力有限。下图是中央处理器的寄存器传输层的简化设计概念。
数据路径的部分单元改造自Harris & Harris的教材“Digital Design and Computer Architecture“的微架构例子。为了方便,我们假设内存分为数据内存和指令内存。可见CPU拥有常规的5级流水线(Instruction Fetch, Instruction Decode, Execute, Memory, Write Back),并有两份数据路径,因此超纯量,理想化下每周期可同时执行10个指令。
蓝线圈的是流水线的执行组件。
红线圈的是数据路径,两个完全相同
在HDL中,我将命名两个运行指令为I0和I1或Instr0和Instr1,PC为PC0和PC1,下周期PC为PC0F,PC1F。
CPU的完整硬件生成:
我的设计中最有趣(也是最难完成)的部分是名为IFHU(Instruction Flow and Hazard Unit)的指令流动及数据冒险控制单元。
原稿:
它内置了一个小型三级流水线,目的就是为了储存(如果存在)指令的RD(Destination Register),Register File的目标地址。地址在IFHU内的流动模拟了真正指令在处理器流水线的执行完成度,因此每次PC从指令内存读出对应指令后,指令如果是BEQ,R- Type或I-Type,他们的根寄存器的地址(RS,RT)将于存在于IFHU流水线内的RD做对比,如果有相同地址代表会出现数据冒险。这些结果会输出到IFU(Instruction Flow Unit),指令控制单元,它按照以下原理决定最终指令是否为空指令以及下周期PC的值:
1. I0和I1正常:执行两个指令,PC0,PC1 + 8
2. I1出现跳跃,分支,或数据冒险:执行I0,PC0 = PC1,PC1 + 4
3. I0出现数据冒险:不执行,PC都不变
4. I0出现跳跃或分支:内部执行,PC0为预测或跳跃后PC,PC1 = PC0 + 4
不出错的话PC1应该永远等于PC0。
下面是IFU:
IFHURegSelect:
IFHUXORComp:
IFHU的另一个重要的组件是一个简单的2位分支预测器。目前我的CPU只支持BEQ(Branch on Equal)这一个分支指令,不过剩下的也都是这一个来的。这是分支预测器FSM:
设三个状态位元为S2S1S0。主要状态Predict Taken,Weak Not Taken,和Strong Not Taken分别有自己的子状态In Progress,In Progress表示已做预测,不知结果,在这个状态下不会再做预测,确保流水线最多执行一个分支预测。根据上面的FSM,可得出一个下个状态的真值表:
分支预测器将先把两个可能的PC存进FF,然后使用预测的方向(S1)选择预测PC。同时一个相反方向的电路(~S1)将选择相反的PC,最终由BRsuccess(预测是否成功)来选择最终输出到IFU。
接下来的指令解码流程就比较直接了。MIPS指令需要读取的寄存器地址直接输进32x32位的寄存器,结果读到RDXX。从这里起,将会有两个数据路径以及两个控制单元。
寄存器或许也同时要储存四个周期前的指令的计算结果或内存数据,WA[4:0]是写入地址,WD[31:0]是写入内容,寄存器的CLK依然和处理器同步但 FF在Falling Edge更换,保持同周期完成。SigExt是Sign Extend的缩写,它负责把指令的Immediate从16位扩到32位。
32x32位的寄存器矩阵:
控制单元:
执行单元的输出ALUcontrol控制ALU的功能:
RegWrite和MemWrite控制寄存器和内存是否写入,RISel控制执行单元ALU的第二个输入使用寄存器内容还是Imm。这些控制电路会如数据电路往流水线的下一个阶段进行。
接下来是 EU(Execution Unit),执行单元。EU以目前支持的指令来看,只需要一个多功能ALU,以后可以加一个FPU和支持SIMD扩展的计算单元。另外RD1读出的内容直接接到WriteData逻辑,在SW指令里,这个将直接写入数据内存。RegAddr是R-Type或I-Type指令的Write Back地址,因为地址在这两类指令里的位置不一样,控制单元根据OPCode输出的RISel逻辑会选择对应的地址
R-Type:0000 00ss ssst tttt ddddd000 0010 0101 (Write Back地址为d)
I-Type:1000 11ss ssst ttttiiii iiii iiii iiii (Write Back地址为t)
ALU的设计很简单,控制单元根据Funct输出的ALUcontrol[1:0]控制ALU的功能。现在只需要ADD,SUB,AND,OR。我这里懒省事了,本来想自己写个Carry Look-Ahead Adder但是时间来不及,直接用SV的“+”了。
这是用ModelSim测试EU的结果:
结果都正确。
接下来测一下IFHU,我用以下六个指令
如果正常的话,IFHU应该并行执行指令1和2,到第二个周期,指令4有冒险,因此IFHU应该只执行指令3,并继续读取指令4和5,这两个都依然有冒险,所以在第三周期PC不变。
汇编器的结果:
ModelSIm运行指令:(完全列出来)
结果:
细看一下第一周期的结果:
可见两个指令都顺利通过,PC都加8
第二周期:
这里的I1F为0开头,代表空指令,PC0 = PC1,而PC1 = PC1 + 4
第三周期:
两个指令都成空指令,PC也不变,根预料的一样。目前IFHU未发现大问题,指令流动正常。
剩下的就不多说了,MEM和WB都很直接。如果不是马上要考期末了,我会再加点指令,再仔细测测所有单元。本来还想来个乱序执行设计,再放个寄存器重命名单元和保留站,但现在的能力有限,我想先读几本更深的教材。接下来我把几个主要Module的描述发出来。
-
cpu
+关注
关注
68文章
10826浏览量
211158 -
MIPS32架构
+关注
关注
0文章
1浏览量
4465
发布评论请先 登录
相关推荐
评论