一、流水线CPU概述
1、流水线CPU的原理
流水线CPU是为提高吞吐量而创造的,五段式流水线CPU的吞吐量是单周期CPU的五倍,同一时间CPU上最多有五条指令在运行。如何达到同一CPU上五条指令呢?答案就在于把每条指令都拆分成五个阶段,按照CPU硬件执行流来拆成五段:IF(instruction fetch)、DEC(decode)、EXE(execute)、ME(memory)、WB(write back),CPU上五段部分分别执行一条指令的一个阶段。
因为CPU上五段分别进行不同指令的不同阶段,每段都需要自己当前执行指令的数据:IF段所用数据为指令地址,可有pc寄存器提供;DE、EXE、ME、WB段所用数据包含但不限于指令内容,一定需要对应流水线寄存器保存。
2、流水线CPU设计的难点
流水线CPU同时有多条指令运行,一个很重要的设计因素是解决冲突。冲突包含硬件冲突、控制冲突和数据冲突。
-
硬件冲突
硬件冲突是说同一时刻需要对同一互斥硬件(一次只允许一次读或写)进行访问,举例来说,D段需要从存储器中取出指令,M段需要对存储器写入数据,这两个操作同时进行就会带来冲突,在这里IM和DM是独立的两个存储器,因此不必考虑。
-
控制冲突
控制冲突是分支指令和跳转指令带来的冲突。分支指令的最终分支地址晚于下一周期到来,导致下一条指令的地址不能及时算出或者决定;跳转指令的跳转地址晚于下一周期到来,导致上述同样冲突。解决这样的冲突主要是通过假设不跳转或者延迟槽。假设不跳转是说先假设不跳转和分支,正常执行下一条指令,当计算出要跳转时清楚已执行的结果。延迟槽是说跳转指令后面加空指令nop,即等待跳转地址计算出来再决定是继续下一条指令还是跳转。
-
数据冲突
数据冲突是关于数据“新鲜性”的冲突。指令的执行离不开寄存器,有的指令会利用寄存器数据,有的指令会写回寄存器,有的指令两者皆有,当前序执行的指令的目的寄存器(将要写回的寄存器)和后序执行的指令的源寄存器(利用其数据的寄存器)相同时,就存在数据关联。当前序指令数据还未写入寄存器,后序指令就要用到该数据时,就会产生错误(冲突)。解决这种冲突需要暂停或者转发:当前序指令的“新”将要写回寄存器的数据(计算)赶不及后序指令使用其数据时就需要暂停后序指令,直到前序指令的“新”数据准备好;当前序指令的“新”数据能赶上后序指令的使用,当前序指令的“新”数据准备好后,转发给后序指令当前所处阶段的流水线寄存器,以达到更新数据的效果。
注意:以下是笔者设计流水线的流程(吃百家饭得来)
二、流水线CPU的功能设计
1、支持指令
str | ld | cal_r | cal_i | lui | b_type | j | jr | jal | jalr | shamt | mod |
---|---|---|---|---|---|---|---|---|---|---|---|
sw | lw | addu | ori | beq | sll | mult | |||||
sb | lb | add | xori | bne | sra | multu | |||||
sh | lh | subu | andi | blez | srl | div | |||||
lbu | sub | addiu | bgtz | divu | |||||||
lhu | sllv | addi | bltz | ||||||||
srav | sltiu | bgez | |||||||||
srlv | slti | ||||||||||
and | |||||||||||
or | |||||||||||
xor | |||||||||||
nor | |||||||||||
slt | |||||||||||
sltu |
2、流水线寄存器
流水线寄存器记录上一阶段的数据并保持,供所在阶段使用,因此每阶段寄存器所需数据如下:
D | E | M | W |
---|---|---|---|
IR | IR | IR | IR |
RD | |||
AO | AO | ||
RD1 | |||
EXTD | EXTD | EXTD | |
RD2 | RD2 | ||
PC4 | |||
PC8 | PC8 | PC8 | PC8 |
PC | PC | PC | PC |
TNEW_E | TNEW_M | ||
HI | HI | ||
LO | LO |
3、所需硬件
先不考虑所有冲突而只考虑执行指令,和单周期CPU的功能硬件设计一样,列出所需硬件,不一样的是指令分五段执行,硬件也可分阶段列出。
本表不包含多选器,多选器在整合数据通路时给出。
下面列出的硬件中有三个值得说明:
-
BEEXT和RDEXT
支持指令中有sh,sb,lh,lhu,lb,lbu这些对半字、字节操作的指令,但是存储器是按照字读或者写的,因此对于存储指令需要BEEXT给出字节选择信号,对于加载指令需要RDEXT处理读出的字。
BEEXT接受的输入为AO_M1_0和三个布尔信号(分别代表指令是否为sw,sh,sb)。AO_M1_0意义是ALU输出在M段结果的低两位,也就是写入地址对4取模的结果(一个字4字节)。BEEXT产生的输出是四位信号,分别表示将要存储的数据的四个字节是否存储。
RDEXT接受的输入为AO_W1_0、RD_W和五个布尔信号(分别表示指令是否是lw,lh,lhu,lb,lbu)。AO_W1_0是ALU输出在W段结果的低两位,也就是读出地址对4取模的结果。RD_W是DM中读出的字。按照五条指令的要求分别对RD_W处理,最后根据五个布尔信号选择一个输出。
-
MDU
乘除运算单元和hi,lo寄存器所在。whi和wlo是hi,lo寄存器的写入信号。start是乘除运算的启动信号,busy是乘除运算进行中的信号。这里乘法模拟用5个时钟周期完成(start后的第一个上升沿开始,busy高亮五个周期),除法模拟用10个时钟周期完成。
阶段 | module | input | output | 功能描述 |
---|---|---|---|---|
IF | PC | D | Q | |
ADD4 | PC | PC4 | ||
ADD8 | PC | PC8 | ||
IM | IA | IR | ||
DE | RF | A1 | RD1 | 从寄存器堆读出寄存器数据 |
A2 | RD2 | |||
EXT | I16 | EXTD | 选择输出SIMM,LIMM,UIMM | |
EXTOP | ||||
CMP0 | FRSD | LESS | 输出和0比较的结果,独热输出 | |
GREAT | ||||
LE_EQ | ||||
GR_EQ | ||||
CMP | D1 | RES | 输出比较结果 | |
D2 | ||||
NPC | PC4 | NEXTPC | 选择输出BPC,JPC | |
I26 | ||||
NPCOP | ||||
EX | MDU | NUM1 | BUSY | 乘除模块,WHI,WLO为写使能,WDHI,WDLO为写入数据 |
NUM2 | HI | |||
MDUOP | LO | |||
START | ||||
WHI | ||||
WLO | ||||
ALU | A | AO | 执行不同操作 | |
B | ||||
SHAMT | ||||
ALUOP | ||||
ME | BEEXT | AO_M1_0 | BE | 得到字节写入使能信号,为1的那一位代表对应dm中的字相应部分写入字节 |
SW_M | ||||
SH_M | ||||
SB_M | ||||
DM | DA[11:2] | RD | 支持写入字节、半字、字和读出字 | |
WD | ||||
WM | ||||
BE[3:0] | ||||
WB | RDEXT | RD_W | RDEXTD | 将dm中取出的字按照指令做相应处理得到将写入rf的字 |
AO_W1_0 | ||||
LW_W | ||||
LHU_W | ||||
LH_W | ||||
LBU_W | ||||
LB_W | ||||
RF | A3 | |||
WD3 | ||||
WR |
4、数据通路
将流水线寄存器和功能硬件针对每一条指令连接起来。
模块 | INPUT | NOP | LD | STR | CAL_R | CAL_I | SHAMT | LUI | J | JR | JAL | JALR | B_TYPE | MDU |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
PC | D | |||||||||||||
ADD4 | PC | Q | Q | Q | Q | Q | Q | Q | Q | Q | Q | Q | ||
ADD8 | PC | Q | Q | |||||||||||
IM | IA | Q | Q | Q | Q | Q | Q | Q | Q | Q | Q | Q | Q | Q |
PC | D | PC4 | PC4 | PC4 | PC4 | PC4 | PC4 | PC4 | PC4 | PC4 | ||||
REG_D | IR_D | IR | IR | IR | IR | IR | IR | IR | IR | IR | IR | IR | IR | IR |
PC4_D | PC4 | PC4 | PC4 | |||||||||||
PC8_D | PC8 | PC8 | ||||||||||||
RF | A1 | IR_D[RS] | IR_D[RS] | IR_D[RS] | IR_D[RS] | IR_D[RS] | IR_D[RS] | IR_D[RS] | IR_D[RS] | |||||
A2 | IR_D[RT] | IR_D[RT] | IR_D[RT] | IR_D[RT] | ||||||||||
EXT | I16 | IR_D[I16] | IR_D[I16] | IR_D[I16] | IR_D[I16] | |||||||||
CMP | D1 | RD1 | ||||||||||||
D2 | RD2 | |||||||||||||
CMP0 | FRSD | FRSD | ||||||||||||
NPC | PC4 | PC4_D | PC4_D | PC4_D | ||||||||||
I26 | IR_D[I26] | IR_D[I26] | IR_D[I16] | |||||||||||
PC | D | NEXTPC | RD1 | NEXTPC | RD1 | NEXTPC/PC4 | ||||||||
REG_E | IR_E | IR_D | IR_D | IR_D | IR_D | IR_D | IR_D | IR_D | IR_D | IR_D | IR_D | IR_D | IR_D | IR_D |
RS_E | RD1 | RD1 | RD1 | RD1 | RD1 | |||||||||
EXT_E | EXTD | EXTD | EXTD | EXTD | ||||||||||
RT_E | RD2 | RD2 | RD2 | RD2 | ||||||||||
PC8_E | PC8_D | PC8_D | ||||||||||||
MDU | NUM1 | RS_E | ||||||||||||
NUM2 | RT_E | |||||||||||||
ALU | A | RS_E | RS_E | RS_E | RS_E | |||||||||
B | EXT_E | EXT_E | RT_E | EXT_E | RT_E | |||||||||
SHAMT | IR_E[SH] | |||||||||||||
REG_M | IR_M | IR_E | IR_E | IR_E | IR_E | IR_E | IR_E | IR_E | IR_E | IR_E | IR_E | IR_E | IR_E | IR_E |
AO_M | AO | AO | AO | AO | AO | |||||||||
RT_M | RT_E | |||||||||||||
PC8_M | PC8_E | PC8_E | ||||||||||||
EXT_M | EXT_E | |||||||||||||
HI_M | ||||||||||||||
LO_M | ||||||||||||||
BEEXT | AO_M1_0 | AO_M[1:0] | ||||||||||||
DM | DA | AO_M | AO_M | |||||||||||
WD | RT_M | |||||||||||||
BE | BE | |||||||||||||
REG_W | IR_W | IR_M | IR_M | IR_M | IR_M | IR_M | IR_M | IR_M | IR_M | IR_M | IR_M | IR_M | IR_M | IR_M |
RD_W | RD | |||||||||||||
AO_W | AO_M | AO_M | AO_M | AO_M | ||||||||||
PC8_W | PC8_M | PC8_M | ||||||||||||
EXT_W | EXT_M | |||||||||||||
HI_W | ||||||||||||||
LO_W | ||||||||||||||
RDEXT | RD_W | RD_W | ||||||||||||
AO_W1_0 | AO_W[1:0] | |||||||||||||
RF | A3 | IR_W[RT] | IR_W[RD] | IR_W[RT] | IR_M[RD] | IR_W[RT] | $31 | IR_W[RD] | ||||||
WD3 | RDEXTD | AO_W | AO_W | AO_W | EXT_W | PC8_W | PC8_W |
5、整合数据通路
将上面的数据通路整合起来,得到硬件间的连接情况。当某一硬件的某一端口前输入来源不唯一时,需添加多选器来选择一个作为输入。
外模块 | 内模块 | 输入 | 复用器 | 选择信号 | |||||||
---|---|---|---|---|---|---|---|---|---|---|---|
IFU | PC | Q | PC4 | NEXTPC | RD1 | MFPC | PCSEL | ||||
ADD4 | PC | Q | |||||||||
ADD8 | PC | Q | |||||||||
IM | IA | Q | |||||||||
nowstate | |||||||||||
REG_D | IR_D | IR | |||||||||
PC4_D | PC4 | ||||||||||
PC8_D | PC8 | ||||||||||
RFU | RF | A1 | IR_D[RS] | ||||||||
A2 | IR_D[RT] | ||||||||||
A3 | IR_W[RT] | IR_W[RD] | 31 | MFA3 | A3SEL | ||||||
WD3 | RDEXTD | AO_W | EXT_W | PC8_W | HI_W | LO_W | MFWD3 | WD3SEL | |||
IDU | EXT | I16 | IR_D[I16] | ||||||||
CMP0 | FRSD | RD1 | |||||||||
CMP | D1 | RD1 | |||||||||
D2 | RD2 | ||||||||||
NPC | PC4 | PC4_D | |||||||||
I26 | IR_D[I26] | ||||||||||
REG_E | IR_E | IR_D | |||||||||
RS_E | RD1 | ||||||||||
EXT_E | EXTD | ||||||||||
RT_E | RD2 | ||||||||||
PC8_E | PC8_D | ||||||||||
EXU | MDU | NUM1 | RS_E | ||||||||
NUM2 | RT_E | RS_E | MFNUM2 | NUM2SEL | |||||||
ALU | A | RS_E | |||||||||
B | EXT_E | RT_E | MFB | BSEL | |||||||
SHAMT | IR_E[SH] | ||||||||||
REG_M | IR_M | IR_E | |||||||||
AO_M | AO | ||||||||||
RT_M | RT_E | ||||||||||
PC8_M | PC8_E | ||||||||||
EXT_M | EXT_E | ||||||||||
HI_M | HI | ||||||||||
LO_M | LO | ||||||||||
MEU | BEEXT | AO_M1_0 | AO_M[1:0] | ||||||||
DM | DA | AO_M | |||||||||
WD | RT_M | ||||||||||
BE | BE | ||||||||||
REG_W | IR_W | IR_M | |||||||||
RD_W | RD | ||||||||||
AO_W | AO_M | ||||||||||
PC8_W | PC8_M | ||||||||||
EXT_W | EXT_M | ||||||||||
HI_W | HI_M | ||||||||||
LO_W | LO_M | ||||||||||
RFU | RDEXT | RD_W | RD_W | ||||||||
AO_W1_0 | AO_W[1:0] |
6、控制信号
列出所有指令的控制信号表。
TYPE | 指令 | INPUT | OUTPUT | ||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
OP | FUNCT | RT | PCSEL | EXTOP | NPCOP | ALUCTRL | ALUOP | BSEL | START | MDUOP | WHI | WLO | NUM2SEL | WM | A3SEL | WD3SEL | WR | ||
LD | LW | 100011 | X | X | 0 | 0 | X | 0 | 0(+) | 0 | 0 | X | 0 | 0 | X | 0(不写) | 0 | 0 | 1 |
LHU | 100101 | X | X | 0 | 0 | X | 0 | 0(+) | 0 | 0 | X | 0 | 0 | X | 0 | 0 | 0 | 1 | |
LH | 100001 | X | X | 0 | 0 | X | 0 | 0(+) | 0 | 0 | X | 0 | 0 | X | 0 | 0 | 0 | 1 | |
LBU | 100100 | X | X | 0 | 0 | X | 0 | 0(+) | 0 | 0 | X | 0 | 0 | X | 0 | 0 | 0 | 1 | |
LB | 100000 | X | X | 0 | 0 | X | 0 | 0(+) | 0 | 0 | X | 0 | 0 | X | 0 | 0 | 0 | 1 | |
STR | SW | 101011 | X | X | 0 | 0 | X | 0 | 0(+) | 0 | 0 | X | 0 | 0 | X | 1 | X | X | 0 |
SH | 101001 | X | X | 0 | 0 | X | 0 | 0(+) | 0 | 0 | X | 0 | 0 | X | 1 | X | X | 0 | |
SB | 101000 | X | X | 0 | 0 | X | 0 | 0(+) | 0 | 0 | X | 0 | 0 | X | 1 | X | X | 0 | |
CAL_R | ADD | 000000 | 100000 | X | 0 | X | X | 15 | 0 | 1 | 0 | X | 0 | 0 | X | 0 | 1 | 1 | 1 |
ADDU | 000000 | 100001 | X | 0 | X | X | 15 | 0 | 1 | 0 | X | 0 | 0 | X | 0 | 1 | 1 | 1 | |
SUB | 000000 | 100010 | X | 0 | X | X | 15 | 1 | 1 | 0 | X | 0 | 0 | X | 0 | 1 | 1 | 1 | |
SUBU | 000000 | 100011 | X | 0 | X | X | 15 | 1 | 1 | 0 | X | 0 | 0 | X | 0 | 1 | 1 | 1 | |
SLLV | 000000 | 000100 | X | 0 | X | X | 15 | 4 | 1 | 0 | X | 0 | 0 | X | 0 | 1 | 1 | 1 | |
SRAV | 000000 | 000111 | X | 0 | X | X | 15 | 5 | 1 | 0 | X | 0 | 0 | X | 0 | 1 | 1 | 1 | |
SRLV | 000000 | 000110 | X | 0 | X | X | 15 | 6 | 1 | 0 | X | 0 | 0 | X | 0 | 1 | 1 | 1 | |
AND | 000000 | 100100 | X | 0 | X | X | 15 | 10 | 1 | 0 | X | 0 | 0 | X | 0 | 1 | 1 | 1 | |
OR | 000000 | 100101 | X | 0 | X | X | 15 | 2 | 1 | 0 | X | 0 | 0 | X | 0 | 1 | 1 | 1 | |
XOR | 000000 | 100110 | X | 0 | X | X | 15 | 11 | 1 | 0 | X | 0 | 0 | X | 0 | 1 | 1 | 1 | |
NOR | 000000 | 100111 | X | 0 | X | X | 15 | 12 | 1 | 0 | X | 0 | 0 | X | 0 | 1 | 1 | 1 | |
SLT | 000000 | 101010 | X | 0 | X | X | 15 | 3 | 1 | 0 | X | 0 | 0 | X | 0 | 1 | 1 | 1 | |
SLTU | 000000 | 101011 | X | 0 | X | X | 15 | 13 | 1 | 0 | X | 0 | 0 | X | 0 | 1 | 1 | 1 | |
SHAMT | SLL | 000000 | 000000 | X | 0 | X | X | 15 | 7 | 1 | 0 | X | 0 | 0 | X | 0 | 1 | 1 | 1 |
SRL | 000000 | 000010 | X | 0 | X | X | 15 | 9 | 1 | 0 | X | 0 | 0 | X | 0 | 1 | 1 | 1 | |
SRA | 000000 | 000011 | X | 0 | X | X | 15 | 8 | 1 | 0 | X | 0 | 0 | X | 0 | 1 | 1 | 1 | |
CAL_I | ORI | 001101 | X | X | 0 | 2 | X | 2 | 2 | 0 | 0 | X | 0 | 0 | X | 0 | 0 | 1 | 1 |
XORI | 001110 | X | X | 0 | 2 | X | 11 | 11 | 0 | 0 | X | 0 | 0 | X | 0 | 0 | 1 | 1 | |
ANDI | 001100 | X | X | 0 | 2 | X | 10 | 10 | 0 | 0 | X | 0 | 0 | X | 0 | 0 | 1 | 1 | |
SLTIU | 001011 | X | X | 0 | 0 | X | 13 | 13 | 0 | 0 | X | 0 | 0 | X | 0 | 0 | 1 | 1 | |
SLTI | 001010 | X | X | 0 | 0 | X | 3 | 3 | 0 | 0 | X | 0 | 0 | X | 0 | 0 | 1 | 1 | |
ADDI | 001000 | X | X | 0 | 0 | X | 0 | 0 | 0 | 0 | X | 0 | 0 | X | 0 | 0 | 1 | 1 | |
ADDIU | 001001 | X | X | 0 | 0 | X | 0 | 0 | 0 | 0 | X | 0 | 0 | X | 0 | 0 | 1 | 1 | |
LUI | 001111 | X | X | 0 | 1 | X | X | X | X | 0 | X | 0 | 0 | X | 0 | 0 | 2 | 1 | |
B_TYPE | BEQ | 000100 | X | X | RES | X | 0 | X | X | X | 0 | X | 0 | 0 | X | 0 | X | X | 0 |
BNE | 000101 | X | X | ~RES | X | 0 | X | X | X | 0 | X | 0 | 0 | X | 0 | X | X | 0 | |
BLEZ | 000110 | X | X | ~GREAT | X | 0 | X | X | X | 0 | X | 0 | 0 | X | 0 | X | X | 0 | |
BGTZ | 000111 | X | X | GREAT | X | 0 | X | X | X | 0 | X | 0 | 0 | X | 0 | X | X | 0 | |
BLTZ | 000001 | X | 00000 | LESS | X | 0 | X | X | X | 0 | X | 0 | 0 | X | 0 | X | X | 0 | |
BGEZ | 000001 | X | 00001 | ~LESS | X | 0 | X | X | X | 0 | X | 0 | 0 | X | 0 | X | X | 0 | |
J | 000010 | X | X | 1 | X | 1 | X | X | X | 0 | X | 0 | 0 | X | 0 | X | X | 0 | |
JR | 000000 | 001000 | X | 2 | X | X | X | X | X | 0 | X | 0 | 0 | X | 0 | X | X | 0 | |
JAL | 000011 | X | X | 1 | X | 1 | X | X | X | 0 | X | 0 | 0 | X | 0 | 2 | 3 | 1 | |
JALR | 000000 | 001001 | X | 2 | X | X | X | X | X | 0 | X | 0 | 0 | X | 0 | 1 | 3 | 1 | |
NOP | 000000 | 000000 | X | 0 | X | X | X | X | X | 0 | X | 0 | 0 | X | 0 | X | X | 0 | |
MOD | MULT | 000000 | 011000 | X | 0 | X | X | X | X | X | 1 | 0 | 0 | 0 | 0 | 0 | X | X | 0 |
MULTU | 000000 | 011001 | X | 0 | X | X | X | X | X | 1 | 1 | 0 | 0 | 0 | 0 | X | X | 0 | |
DIV | 000000 | 011010 | X | 0 | X | X | X | X | X | 1 | 2 | 0 | 0 | 0 | 0 | X | X | 0 | |
DIVU | 000000 | 011011 | X | 0 | X | X | X | X | X | 1 | 3 | 0 | 0 | 0 | 0 | X | X | 0 | |
MFR | MFHI | 000000 | 010000 | X | 0 | X | X | X | X | X | 0 | X | 0 | 0 | X | 0 | 1 | 4 | 1 |
MFLO | 000000 | 010010 | X | 0 | X | X | X | X | X | 0 | X | 0 | 0 | X | 0 | 1 | 5 | 1 | |
MTO | MTHI | 000000 | 010001 | X | 0 | X | X | X | X | X | 0 | X | 1 | 0 | X | 0 | X | X | 0 |
MTLO | 000000 | 010011 | X | 0 | X | X | X | X | X | 0 | X | 0 | 1 | 1 | 0 | X | X | 0 |
三、流水线CPU的冲突解决
0、特别说明
我们现在要考虑流水线CPU的冲突问题,前面说过的三类冲突问题:硬件冲突在这里没有,因为IM和DM的独立;控制冲突通过延迟槽解决,因此硬件上也不需要多余设计(如果用假设不跳转的思路,需要增加流水线寄存器的同步清零信号,以清除错误执行指令的结果,且添加同步清零的控制逻辑);数据冲突是我们着重要考虑的问题,关键在于什么时候暂停,什么时候转发,并且逻辑不能太复杂,经过大佬方法点拨和个人揣摩,我采取如下方法。
1、AT法
AT法是大佬的叫法,按我下面的表格,更适合叫做是SDT法,即源头、目的时间法。
对任意一条标准指令(只涉及通用寄存器的指令),有源头寄存器和目的寄存器:当一条通用指令i需要寄存器s1、寄存器s2的数据时,s1和s2就是i的源头寄存器(不需要用到数据时,s1和s2为0);当一条通用指令i需要写入寄存器des时,des就是i的目的寄存器(不需要写寄存器时,des为0)。
对于源寄存器s有时间tuseD(/E/M),意思是在从D(/E/M)段开始,过几个时钟周期需要使用s里的数据。对于目的寄存器des有数据tnewD(/E/M),意思是从D(/E/M)段开始,过几个时钟周期des的数据被更新。
-
什么时候要暂停
暂停的时刻放在D段,每条指令i在D段时,要和它前面的指令j对照判断,看是否需要暂停:当i的源寄存器和j的目的寄存器相同时(设为寄存器k),i和j存在数据关联,这时如果i的tuse大于j的tnew,代表k中数据还没被j准备好(甚至不能转发过来),这时需要暂停D段指令i,否则i会使用k中旧数据里错误运行。
暂停需要做的工作很简单,将pc和D段流水线寄存器禁止使能,即一直维持当前数据直到D段指令和前序指令没有数据关联或者tuse不大于tnew。
-
何时转发?转发去哪?转发什么?
当前序指令的tnew为0时代表新数据已经准备好,需要立刻转发到前面以备可能的数据冲突。
这里是转发到前面阶段(比如D段)的最开始,紧接着对应阶段的寄存器数据源头(比如RD1、RD2、RS_E、RT_E),和原本流水线寄存器的输出一起被选择(比如多选器MFRSD、MFRTD),当数据关联时就选择转发的数据(比如FRSD、FRTD),否则选择原来数据(比如RD1、RD2)。
转发的是前序指令已经准备好的数据,在每一阶段可以根据指令类别写出待转发数据,得到真值表。
特别的对于W段指令到D段指令的转发,由于W段写入和D段读出都是对于寄存器堆,我们采用内部转发:通过寄存器堆的结构使得,在同一个时钟上升沿,若有数据写入寄存器r,也有从寄存器r读出数据的请求,将将写入数据直接读出。这样一来,W段到D段的数据不再需要外部转发。
对于非通用指令,比如mult、div、mfhi、mflo、mthi、mtlo,通过下表分析可知:它们内部不存在数据冲突,因为写回hi/lo和计算出结果在同一周期内完成;它们和通用指令之间的数据冲突处理方式和前面一样。
S1_D/E/M | TUSE1_ | S1D | MUX | S2_D/E/M | TUSE2_ | S2D | MUX | DES_ | TNEW_ | DESD_ | ||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
D | STR | IR_D[RS] | 1 | RD1 | MFRSD | IR_D[RT] | 2 | RD2 | MFRTD | X | X | X | ||||
LD | IR_D[RS] | 1 | RD1 | MFRSD | $0 | X | X | X | X | |||||||
CAL_R | IR_D[RS] | 1 | RD1 | MFRSD | IR_D[RT] | 1 | RD2 | MFRTD | X | X | X | |||||
SHAMT | $0 | X | IR_D[RT] | 1 | RD2 | MFRTD | X | X | X | |||||||
CAL_I | IR_D[RS] | 1 | RD1 | MFRSD | $0 | X | X | X | X | |||||||
LUI | $0 | X | $0 | X | X | X | X | |||||||||
B_TYPE | IR_D[RS] | 0 | RD1 | MFRSD | IR_D[RT] | 0 | RD2 | MFRTD | X | X | X | |||||
J | $0 | X | $0 | X | X | X | X | |||||||||
JR | IR_D[RS] | 0 | RD1 | MFRSD | $0 | X | X | X | X | |||||||
JAL | $0 | X | $0 | X | X | X | X | |||||||||
JALR | IR_D[RS] | 0 | RD1 | MFRSD | $0 | X | X | X | X | |||||||
MOD | IR_D[RS] | 1 | RD1 | MFRSD | IR_D[RT] | 1 | RD2 | MFRTD | ||||||||
MFHI | HI/$0 | 3 | $0 | X | ||||||||||||
MFLO | LO/$0 | 3 | $0 | X | ||||||||||||
MTHI | IR_D[RS] | 1 | RD1 | MFRSD | $0 | X | ||||||||||
MTLO | IR_D[RS] | 1 | RD1 | MFRSD | $0 | X | ||||||||||
E | STR | IR_E[RS] | 0 | RS_E | MFRSE | IR_E[RT] | 1 | RT_E | MFRTE | $0 | X | X | ||||
LD | IR_E[RS] | 0 | RS_E | MFRSE | $0 | X | IR_E[RT] | 2 | X | |||||||
CAL_R | IR_E[RS] | 0 | RS_E | MFRSE | IR_E[RT] | 0 | RT_E | MFRTE | IR_E[RD] | 1 | X | |||||
SHAMT | $0 | X | IR_E[RT] | 0 | RT_E | MFRTE | IR_E[RD] | 1 | X | |||||||
CAL_I | IR_E[RS] | 0 | RS_E | MFRSE | $0 | X | IR_E[RT] | 1 | X | |||||||
LUI | $0 | X | $0 | X | IR_E[RT] | 0 | EXT_E | |||||||||
B_TYPE | $0 | X | $0 | X | $0 | X | X | |||||||||
J | $0 | X | $0 | X | $0 | X | X | |||||||||
JR | $0 | X | $0 | X | $0 | X | X | |||||||||
JAL | $0 | X | $0 | X | $31 | 0 | PC8_E | |||||||||
JALR | $0 | X | $0 | X | IR_E[RD] | 0 | PC8_E | |||||||||
MOD | IR_E[RS] | 0 | RS_E | MFRSE | IR_E[RT] | 0 | RT_E | MFRTE | HI,LO/$0 | 5,10/X | X | |||||
MFHI | HI/$0 | 2 | HI/X | $0 | X | IR_E[RD] | 1 | X | ||||||||
MFLO | LO/$0 | 2 | LO/X | $0 | X | IR_E[RD] | 1 | X | ||||||||
MTHI | IR_E[RS] | 0 | RS_E | MFRSE | $0 | X | HI/$0 | 0 | X | |||||||
MTLO | IR_E[RS] | 0 | RS_E | MFRSE | $0 | X | LO/$0 | 0 | X | |||||||
M | STR | $0 | X | IR_M[RT] | 0 | RT_M | MFRTM | $0 | X | X | ||||||
LD | $0 | X | $0 | X | IR_M[RT] | 1 | X | |||||||||
CAL_R | $0 | X | $0 | X | IR_M[RD] | 0 | AO_M | |||||||||
SHAMT | $0 | X | $0 | X | IR_M[RD] | 0 | AO_M | |||||||||
CAL_I | $0 | X | $0 | X | IR_M[RT] | 0 | AO_M | |||||||||
LUI | $0 | X | $0 | X | IR_M[RT] | 0 | EXT_M | |||||||||
B_TYPE | $0 | X | $0 | X | $0 | X | X | |||||||||
J | $0 | X | $0 | X | $0 | X | X | |||||||||
JR | $0 | X | $0 | X | $0 | X | X | |||||||||
JAL | $0 | X | $0 | X | $31 | 0 | PC8_M | |||||||||
JALR | $0 | X | $0 | X | IR_M[RD] | 0 | PC8_M | |||||||||
MOD | $0 | X | $0 | X | $0 | X | X | |||||||||
MFHI | HI/$0 | 1 | HI_M/X | $0 | X | IR_M[RD] | 0 | HI_M | ||||||||
MFLO | LO/$0 | 1 | LO_M/X | $0 | X | IR_M[RD] | 0 | LO_M | ||||||||
MTHI | $0 | X | $0 | X | $0 | X | X | |||||||||
MTLO | $0 | X | $0 | X | $0 | X | X | |||||||||
W | STR | X | X | X | X | $0 | X | X |
2、补充所需硬件
经过AT法的分析,每一阶段寄存器数据的源头不再唯一,还包含从后面阶段(前序指令)转发过来的“最新”数据,需要添加相应多选器,这些多选器mux在上表中已然列出。
阶段 | module | input | output | 功能描述 |
---|---|---|---|---|
IF | MFPC | PCSEL | D | 选择下一个pc值 |
PC4 | ||||
NEXTPC | ||||
RD1/FRSD | ||||
PC | D | Q | ||
ADD4 | PC | PC4 | ||
ADD8 | PC | PC8 | ||
IM | IA | IR | ||
DE | RF | A1 | RD1 | 从寄存器堆读出寄存器数据 |
A2 | RD2 | |||
MFRSD | FRSDSEL | FRSD | 选择转发到D级rs寄存器的值 | |
RD1 | ||||
ETOD | E段转发到D段的数据,下同 | |||
MTOD | ||||
MFRTD | FRTDSEL | FRTD | 选择转发到D级rt寄存器的值 | |
RD2 | ||||
ETOD | ||||
MTOD | ||||
EXT | I16 | EXTD | 选择输出SIMM,LIMM,UIMM | |
EXTOP | ||||
CMP0 | FRSD | LESS | 输出和0比较的结果,独热输出 | |
GREAT | ||||
LE_EQ | ||||
GR_EQ | ||||
CMP | D1 | RES | 输出比较结果 | |
D2 | ||||
NPC | PC4 | NEXTPC | 选择输出BPC,JPC | |
I26 | ||||
NPCOP | ||||
EX | MFRSE | FRSESEL | FRSE | 选择转发到E级rs寄存器的值 |
RS_E | ||||
MTOE | ||||
WTOE | ||||
MFRTE | FRTESEL | FRTE | 选择转发到E级rt寄存器的值 | |
RT_E | ||||
MTOE | ||||
WTOE | ||||
MFNUM2 | FRTE | NUM2 | 选择输入num2 | |
FRSE | ||||
MDU | NUM1 | BUSY | 乘除模块,WHI,WLO为写使能,WDHI,WDLO为写入数据 | |
NUM2 | HI | |||
MDUOP | LO | |||
START | ||||
WHI | ||||
WLO | ||||
MFB | BSEL | B | 选择alu的b输入 | |
EXT_E | ||||
FRTE | ||||
ALU | A | AO | 执行不同操作 | |
B | ||||
SHAMT | ||||
ALUOP | ||||
ME | MFRTM | FRTMSEL | FRTM | 选择转发到M级rt寄存器的值 |
RT_M | ||||
WTOM | ||||
BEEXT | AO_M1_0 | BE | 得到字节写入使能信号,为1的那一位代表对应dm中的字相应部分写入字节 | |
SW_M | ||||
SH_M | ||||
SB_M | ||||
DM | DA[11:2] | RD | 支持写入字节、半字、字和读出字 | |
WD | ||||
WM | ||||
BE[3:0] | ||||
WB | RDEXT | RD_W | RDEXTD | 将dm中取出的字按照指令做相应处理得到将写入rf的字 |
AO_W1_0 | ||||
LW_W | ||||
LHU_W | ||||
LH_W | ||||
LBU_W | ||||
LB_W | ||||
MFA3 | A3SEL | A3 | 选择a3 | |
IR_W[RT] | ||||
IR_W[RD] | ||||
31 | ||||
MFWD3 | WD3SEL | WD3 | 选择wd3 | |
RDEXTD | ||||
AO_W | ||||
EXT_W | ||||
PC8_W | ||||
RF | A3 | |||
WD3 | ||||
WR |
3、修改数据通路
经过转发数据mux选择后的数据作为新的所在阶段寄存器数据的源头。
外模块 | 内模块 | 端口 | 复用器 | 选择信号 | |||||||
---|---|---|---|---|---|---|---|---|---|---|---|
IFU | PC | Q | PC4 | NEXTPC | RD1/FRSD | MFPC | PCSEL | ||||
ADD4 | PC | Q | |||||||||
ADD8 | PC | Q | |||||||||
IM | IA | Q | |||||||||
nowstate | |||||||||||
REG_D | IR_D | IR | |||||||||
PC4_D | PC4 | ||||||||||
PC8_D | PC8 | ||||||||||
RFU | RF | A1 | IR_D[RS] | ||||||||
A2 | IR_D[RT] | ||||||||||
A3 | IR_W[RT] | IR_W[RD] | $31 | MFA3 | A3SEL | ||||||
WD3 | RDEXTD | AO_W | EXT_W | PC8_W | HI_W | LO_W | MFWD3 | WD3SEL | |||
MFRSD | FRSDSEL | ||||||||||
RD1 | |||||||||||
ETOD | |||||||||||
MTOD | |||||||||||
MFRTD | FRTDSEL | ||||||||||
RD2 | |||||||||||
ETOD | |||||||||||
MTOD | |||||||||||
IDU | EXT | I16 | IR_D[I16] | ||||||||
CMP0 | FRSD | RD1/FRSD | |||||||||
CMP | D1 | RD1/FRSD | |||||||||
D2 | RD2/FRTD | ||||||||||
NPC | PC4 | PC4_D | |||||||||
I26 | IR_D[I26] | ||||||||||
REG_E | IR_E | IR_D | |||||||||
RS_E | RD1/FRSD | ||||||||||
EXT_E | EXTD | ||||||||||
RT_E | RD2/FRTD | ||||||||||
PC8_E | PC8_D | ||||||||||
EXU | MFRSE | FRSESEL | |||||||||
RS_E | |||||||||||
MTOE | |||||||||||
WTOE | |||||||||||
MFRTE | FRTESEL | ||||||||||
RT_E | |||||||||||
MTOE | |||||||||||
WTOE | |||||||||||
MDU | NUM1 | RS_E/FRSE | |||||||||
NUM2 | RT_E/FRTE | RS_E/FRSE | MFNUM2 | NUM2SEL | |||||||
ALU | A | RS_E/FRSE | |||||||||
B | EXT_E | RT_E/FRTE | MFB | BSEL | |||||||
SHAMT | IR_E[SH] | ||||||||||
REG_M | IR_M | IR_E | |||||||||
AO_M | AO | ||||||||||
RT_M | RT_E/FRTE | ||||||||||
PC8_M | PC8_E | ||||||||||
EXT_M | EXT_E | ||||||||||
HI_M | HI | ||||||||||
LO_M | LO | ||||||||||
MEU | MFRTM | FRTMSEL | |||||||||
RT_M | |||||||||||
WTOM | |||||||||||
BEEXT | AO_M1_0 | AO_M[1:0] | |||||||||
DM | DA | AO_M | |||||||||
WD | RT_M/FRTM | ||||||||||
BE | BE | ||||||||||
REG_W | IR_W | IR_M | |||||||||
RD_W | RD | ||||||||||
AO_W | AO_M | ||||||||||
PC8_W | PC8_M | ||||||||||
EXT_W | EXT_M | ||||||||||
HI_W | HI_M | ||||||||||
LO_W | LO_M | ||||||||||
RFU | RDEXT | RD_W | RD_W | ||||||||
AO_W1_0 | AO_W[1:0] |
四、结束
到此,简化五段式流水线CPU就已经设计完毕,Verilog代码就不放出来了,代码量庞大。
说明一下,文中写的通用指令和非通用指令是自创的,没有严格定义,只是区分一下。
本文是对笔者学习思考CPU的一点总结,供复习所用,若能帮到读者就最好不过了。
感谢阅读,若有错误,请评论给出,万分感谢。