流水线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段所用数据包含但不限于指令内容,一定需要对应流水线寄存器保存。
流水线CPU同时有多条指令运行,一个很重要的设计因素是解决冲突。冲突包含硬件冲突、控制冲突和数据冲突。
硬件冲突是说同一时刻需要对同一互斥硬件(一次只允许一次读或写)进行访问,举例来说,D段需要从存储器中取出指令,M段需要对存储器写入数据,这两个操作同时进行就会带来冲突,在这里IM和DM是独立的两个存储器,因此不必考虑。
控制冲突是分支指令和跳转指令带来的冲突。分支指令的最终分支地址晚于下一周期到来,导致下一条指令的地址不能及时算出或者决定;跳转指令的跳转地址晚于下一周期到来,导致上述同样冲突。解决这样的冲突主要是通过假设不跳转或者延迟槽。假设不跳转是说先假设不跳转和分支,正常执行下一条指令,当计算出要跳转时清楚已执行的结果。延迟槽是说跳转指令后面加空指令nop,即等待跳转地址计算出来再决定是继续下一条指令还是跳转。
数据冲突是关于数据“新鲜性”的冲突。指令的执行离不开寄存器,有的指令会利用寄存器数据,有的指令会写回寄存器,有的指令两者皆有,当前序执行的指令的目的寄存器(将要写回的寄存器)和后序执行的指令的源寄存器(利用其数据的寄存器)相同时,就存在数据关联。当前序指令数据还未写入寄存器,后序指令就要用到该数据时,就会产生错误(冲突)。解决这种冲突需要暂停或者转发:当前序指令的“新”将要写回寄存器的数据(计算)赶不及后序指令使用其数据时就需要暂停后序指令,直到前序指令的“新”数据准备好;当前序指令的“新”数据能赶上后序指令的使用,当前序指令的“新”数据准备好后,转发给后序指令当前所处阶段的流水线寄存器,以达到更新数据的效果。
| 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 |
流水线寄存器记录上一阶段的数据并保持,供所在阶段使用,因此每阶段寄存器所需数据如下:
| 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 |
先不考虑所有冲突而只考虑执行指令,和单周期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 |
将流水线寄存器和功能硬件针对每一条指令连接起来。
| 模块 | 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 |
将上面的数据通路整合起来,得到硬件间的连接情况。当某一硬件的某一端口前输入来源不唯一时,需添加多选器来选择一个作为输入。
| 外模块 | 内模块 | 输入 | 复用器 | 选择信号 | |||||||
|---|---|---|---|---|---|---|---|---|---|---|---|
| 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] |
列出所有指令的控制信号表。
| 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的冲突问题,前面说过的三类冲突问题:硬件冲突在这里没有,因为IM和DM的独立;控制冲突通过延迟槽解决,因此硬件上也不需要多余设计(如果用假设不跳转的思路,需要增加流水线寄存器的同步清零信号,以清除错误执行指令的结果,且添加同步清零的控制逻辑);数据冲突是我们着重要考虑的问题,关键在于什么时候暂停,什么时候转发,并且逻辑不能太复杂,经过大佬方法点拨和个人揣摩,我采取如下方法。
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 |
经过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 |
经过转发数据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的一点总结,供复习所用,若能帮到读者就最好不过了。
感谢阅读,若有错误,请评论给出,万分感谢。
原文:https://www.cnblogs.com/behang/p/14984186.html