数电第八章 CPU
中央处理器概述
指令执行过程时有异常,则自动切换到异常处理程序,硬件检测是否有中断请求,有则转中断处理。
异常和中断的差别:异常是在CPU内部发生的,中断是由外部事件引起的。
CPU 由执行部件(数据通路:存储元件时序逻辑、操作原件组合逻辑)和控制部件(控制器(负责对执行部件发出控制信号):译码部件组合逻辑、控制信号生成部件组合逻辑、存储元件时序逻辑)组成,即数据通路与控制单元
数据通路(DataPath)——指令的执行部件(操作元件(组合逻辑)(如ALU)存储(状态)元件(时序逻辑)寄存器)
数据通路是由操作元件和存储元件通过总线方式或分散方式连接而成的进行数据存储、处理、传送的路径。
计算机性能分析
主要有两种:(1)响应/执行时间、时延(2)吞吐率、带宽。
CPI指每个时钟周期内可执行的指令条数。计算:设\(CPI_i,C_i\)分别为第类指令的CPI和指令条数,时钟周期为\(T\),程序总时钟数为\(\displaystyle \sum_{i}CPI_i\cdot C_i\),CPU执行时间为\(\displaystyle T\cdot \sum_{i}CPI_i\cdot C_i\)
故\(\displaystyle CPI=\frac{CPU时间\cdot 时钟频率}{指令条数}\)
CPI越小并不意味着运算时间变短,其还与时钟周期宽度有关。
单周期数据通路设计
每一条指令在进行其对应的特殊操作前,需先取当前指令,并将PC+4,指向下一条指令。
在RV32I种只能通过load/Store指令访问存储器数据,数据地址通过一个32位寄存器内容加12位偏移量(需做符号扩展)得到。
RegWr:是否需要回写结果到寄存器内?
ALUctr:计算控制信号
ExtOP:立即数扩展信号
opcode:操作码(一般6位)
funct7,funct3(功能码,一般7/3位)

R-型指令(寄存器操作数指令)的数据通路
1 2 3 4 5 6 | |
三条指令的ALUctr分别为add,slt,sltu;RegWr=1
I-型指令(短立即数或装入指令)的数据通路
1 2 3 | |
对于Load指令,ALUctr=add,ExtOP=immI,ALUBSrc=1,MemWr=0,MemtoReg=1,RegWr=1
S-型指令(存储指令)的数据通路
1 2 | |
ALUctr=add,ExtOP=immS,ALUBSrc=1,MemWr=1,MemtoReg=x,RegWr=0
B-型指令(条件跳转指令)的数据通路
1 2 | |
ALUctr=sub,ExtOP=immB,ALUBSrc=0,MemWr=0,MemtoReg=x,RegWr=0,Branch=1
U-型指令(长立即数操作指令)的数据通路
1 | |
J-型指令(无条件跳转指令)的数据通路
1 2 | |
ALUctr=add,ExtOP=immJ,ALUASrc=1,ALUBSrc=1,MemWr=0,MemtoReg=0,RegWr=1,Branch=0,Jump=1
单周期控制器设计
单周期处理器的CPI为多少?\(\boxed{1}\),单周期时钟宽度为最复杂指令执行所需时间。
lw指令(最长指令)操作定时:Clk-to-Q(PC改变)、取指令时间、控制单元延迟:计算各控制信号并等待其稳定、Register File Access Time(busA,busB(受扩展器与多路选择器的延迟影响)得到新值)、ALU Delay(计算Address,从busAB全部到达起算)、Data Memory Access Time(改变busW)、Setup Time for Register File Write、Clock Skew
多周期处理器设计
单周期处理器的劣势:时钟周期必须以最长的指令为准,时钟周期远大于其他指令实际所需的执行时间,效率低。
解决思路:把指令执行分成大致相等的多个阶段,每个阶段在一个时钟周期内完成,规定每个阶段只能完成1次访存或寄存器堆读/写。每步都设置存储单元(暂存(MAR)),每步的执行结果在下个时钟开始时保存到对应单元。
时钟周期以最复杂阶段所花时间为准,不同指令所用周期数可以不同,允许功能部件在一条指令执行过程中被重复使用。
多周期控制器功能的两种描述方式:
(1)有限状态机:用硬连线路(PLA)实现
- 每个时钟周期包含的控制信号的值的组合看成一个状态,每来一个时钟,控制信号会有一组新的取值,也就是一个新的状态
- 所有指令的执行过程可用一个有限状态转换图来描述
-
用一个组合逻辑电路(一般为PLA电路)来生成控制信号,用一个状态寄存器实现状态之间的转换
-
实现的控制器称为硬布线控制器
10个状态则状态寄存器至少4位。
优点:速度快,适合简单规整的指令系统
缺点:结构庞杂、实现、修改、维护困难,灵活性差
(2)微程序:用只读存储器(控制存储器CS)存放微程序实现
- 每个时钟周期所包含的控制信号的值的组合看成是一个0/1序列,每个控制信号对应一个微命令,控制信号取不同的值,就发出不同的微命令
采用不译法得到微指令:根据各控制信号组成0/1序列。
下一微地址确定方式:
(1)增量(计数器)法:隐含在微程序计数器\(\mu PC\)中
(2)断定(下址字段)法:在本条微指令中明显指定。
- 若干微命令组合成一个微指令,每条指令所包含的动作就由若干条微指令来完成,每来一个时钟,执行一条微指令
- 每条指令对应一个微程序,执行时,先找到对应的第一条微指令,然后按照特定的顺序取出后续的微指令执行
- 实现的控制器称为微程序控制器
优点:规整、可维护、灵活;缺点:速度慢
执行某指令时:
- 从CS中取出对应微程序
- 执行微程序,即执行其中各条微指令
- 微指令译码,产生对应的微命令——控制信号
- 微命令控制数据通路执行
状态转换图:各指令的时钟数:R型:4, I型:4, lw:4, sw:4, Jump:3

异常的基本处理:
(1)关中断(“中断/异常允许”状态位清0):防止新异常(或中断)破坏断点、程序状态和现场(现场指通用寄存器的值)。
(2)保护断点和程序状态:将断点和程序状态保存到堆栈或特殊寄存
PC→栈 或 专门存放断点的寄存器。
PSWR →栈 或 EPSWR (专门保存程序状态的寄存器)
为使流水线顺利工作(解决结构冒险),规定:
- 每个功能部件每条指令只能用一次(写口不能同时被写两次及以上)
- 每个功能部件必须在特定阶段被使用(即使指令不同,如写口总是在第五阶段使用)
- 将寄存器读口、写口独立,将Instruction Memory与Data Memory分开
添加NOP指令进行延迟,使流水线更规整。


理想流水线的CPI为1.(若干阶段后,每一阶段均完成了一条指令)
最开始时刻,所有流水段寄存器初始化为0(信号不能随意置为1,其中(WE)write enable错置为1造成的错写是无法挽回的)
IF:取指令,计算PC+4
ID:译码取数:从寄存器取操作数,立即数扩展、解码指令,得到控制信号
EX:在ALU中对操作数进行计算/得到转移目标地址
M:读/写存储单元
Wr:ALU结果/DM读出数据写寄存器rd
流水段寄存器:
IF/ID:保存后面阶段用到的指令与旧PC的值
ID/EX:保存R[rs1]、R[rs2]、Rd、Imm(由解码所得ExtOP实时扩展得)、PC、各控制信号
EX/M:保存跳转地址、Zero、ALU结果、busB(sw指令要用到)、rd、控制信号
M/Wr:保存内存读出数据、rd、控制信号
结构冒险/资源冲突(已提前解决):一个功能部件同时被不同指令使用(两条指令试图在同一个时钟周期写寄存器,若不对寄存器堆写口、读口独立设置,则发生冲突!)
数据冒险:后面指令用前面指令结果数据时,前面指令结果还未产生(在途中如果某一指令在WB阶段写寄存器,而同时在其后方的指令正在使用此寄存器时,可能发生同一个寄存器同时被读与写,但先后顺序无法保证,可能导致出错。)
控制冒险(分支冒险、转移冒险):转移或异常改变执行流程,后继指令在目标地址产生前已被取出B-指令在取数阶段尚未确定是否应跳转,而紧随其后的指令已经进入流水线,取错了指令!
单周期与流水线计算机的性能对比:
单周期时钟周期为各阶段时钟周期之和,流水线时钟周期为各阶段时钟周期最大值+流水段寄存器延迟。
【考试重点】识别数据冒险现象:
1 2 3 4 5 | |
前三条指令是r1旧值,第五条指令是r1新值,第2、3条指令计算错误,第4条指令不一定能读到新值,我们认为此错误(在读后写的情况下),共出现3对冒险
三类数据冒险现象(仅考虑RAW冒险):
(1)RAW: 写后读(基本流水线中经常发生,如上例)
(2)WAR:读后写(基本流水线中不会发生,乱序执行时会发生)
(3)WAW:写后写(基本流水线中不会发生,乱序执行时会发生)
解决方案:
(1)(纯硬件)硬件阻塞(插入气泡bubble)(阻止后续指令执行,延迟到有新值之后)
使用专门的组合逻辑电路计算阻塞周期数。阻塞时,使流水段寄存器全部填充0。
缺陷:控制较复杂,需修改数据通路,指令被延迟执行,造成时间损耗。
1 2 3 4 5 6 7 8 | |
(2)(纯软件)软件插入NOP指令
由编译器插入NOP指令
优势:无需修改硬件(数据通路),与硬件阻塞相比没有时间优化。
1 2 3 4 5 6 7 8 | |
(3)(纯硬件)(与其他方案搭配)(不能解决所有数据冒险)合理实现寄存器堆读/写操作
寄存器写口/读口分别在前/后半周期进行操作,使写入数据被直接读出(可以消除or运算的数据冒险)
与方案一结合时将只插入2行气泡。
(4)【考试重点】(纯硬件)(不能解决所有数据冒险)转发(Forwading转发或Bypassing旁路)技术
利用DataPath的中间数据:可以在流水段寄存器中找到r1的新值,当add指令计算出r1的新值时,此值暂存EX/M寄存器,此时sub在计算,从段寄存器实时转回r1的值即可,and计算同理。
(5)(纯软件)(不能解决所有数据冒险)编译优化:调整指令顺序
转发技术
绿线指令:t3在绿色线取,因此时t3新结果在EX/M段寄存器中
红线指令:t3在红色线取,因此时t3新结果在M/WB段寄存器中
蓝线指令(慢一步即出现问题):load指令取得的值最早只能在M/WB段寄存器获得,此时满足情况
红框指令:由第三种情况可知,此时取不到load的结果,故无法得到t3新值,无法完成转发

对Load指令引起的延迟现象:若寄存器采取前半后半,则需要阻塞2个周期,否则要阻塞3个周期。
若采用转发技术,必须要阻塞1个周期,否则将引发load—use冒险。
数据冒险处理的最佳方案:转发技术+Load—use阻塞。
当前一条指令为Load且前一条指令的目的寄存器等于当前刚取出指令的源寄存器时,需要阻塞。此时ID/EX段寄存器所有控制信号清零(插入一个气泡),IF/ID寄存器内容不变,当前指令重新译码执行,PC值不变,下一条指令重新被取出执行。

编译优化:源程序可编译生成不同的汇编代码,在此基础上做优化可以尽可能减少Load阻塞(降低\(33\%\sim 50\%\))
控制冒险的现象和对策
B型指令是否转移最早要在M阶段确定,目标地址在此时被送入PC端,在取目标指令前,已取出的指令应全部清除,称发生转移时,给流水线带来的延迟损失为延迟损失时间片\(C\),这里\(C=3\)。
解决方法有四种:(1)阻塞(延迟到分支指令能确定是否转移后)(2)插入NOP(3)分支预测(不能保证全部正确)(4)延迟分支,仍需将方案(3)与方案(1)结合。
静态分支预测技术
总预测条件不满足(不跳转),可添加启发式规则,在特定条件下总是预测满足,其他则总是预测不满足。预测失败时,将流水线中3条错误预测指令丢弃。
一个例子
循环顶部(底部)分支总是预测为不满足(满足),能达65%-85%的预测准确率。
可缩短分支延迟,减小错误预测代价:将转移地址计算和分支条件判断操作调整到ID阶段,预测失败则\(C=1\)
若预测不转移但Branch,Zero=1,则beq预测失败,此时需:转移目标地址写PC,清除IF段取出的指令(相关控制信号置0)。
动态分支预测技术
利用最近转移发生的情况,来预测下一次可能转移还是不转移 ,转移发生的历史情况记录在分支历史记录表(BHT)中。
BHT初始为空,查找是发现均不相等,称为“未命中”,此时加入新项,填入指令地址、转移目标地址,初始化预测位。若命中,则选择转移取/顺序取。
预测位位数设计:1表示最近一次发生过转移,0表示未发生。
根据程序执行的历史情况进行动态预测调整(如循环时,跳转时间是有规律的)。
缩短分支延迟技术
静态调度技术,通过编译程序重排指令顺序,把分支指令前面的与分支指令无关的指令调到分支指令后执行,以填充延迟时间片,与\(C\)相关,不够则用nop填。可能产生新的load—use冒险。
流水线中对另一种控制冒险——异常和中断的处理
一个例子:某指令发现“溢出”时,后面已经有2条指令进入流水线了,此时:
(1)清除此溢出指令及后面的所有已在流水线中的指令
(2)关中断(将中断允许触发器清0)
(3)保存PC或PC-4(断点) 到 EPC
(4)将异常/中断处理程序首地址送PC
单周期、多周期、流水线三种方式的效率比较
一个例子
假设各主要功能单元的操作时间为:存储单元:200ps、ALU和加法器:100ps、寄存器堆(读/写):50ps
假设MUX、控制单元、PC、扩展器和传输线路都没有延迟,指令组成为:25%取数、10%存数、52%ALU、11%分支、2%跳转,则下面实现方式中哪个更快?快多少? (1)单周期:每条指令在一个固定长度的时钟周期内完成
(2)多周期:每类指令时钟数为取数-5,存数-4,ALU-4,分支-3,跳转-3
(3)流水线:每条指令分取指令、取数/译码、执行、存储器存取、写回五阶段
(假定没有结构冒险,数据冒险采用转发处理,分支延迟槽为1,预测准确率为75%;无条件跳转指令的更新地址工作也在ID段完成。不考虑流水段寄存器延时,不考虑异常、中断和访存缺失引起的流水线冒险)
参考解答
(1)单周期:时钟周期将由最长指令——load指令决定,为600ps。N条指令的执行时间为600N(ps)。
(2)多周期:时钟周期将取功能部件最长所需时间,应该是存取操作,为200ps 根据各类指令的频度,计算平均时钟周期数为:\(CPU时钟周期=5\cdot 25\%+4\cdot 10\%+4\cdot 52\%+3\cdot 11\%+3\cdot 2\%=4.12\)
所以,N条指令的执行时间为\(4.12\cdot 200N=824N\)(ps)
(3)流水线:
Load指令:当发生Load-use依赖时,执行时间为2个时钟,否则1个时钟,故平均执行时间为1.5个时钟;
Store、ALU指令:1个时钟;
Branch指令:预测成功:1个时钟,预测错误:2个时钟。平均时钟:\(0.75\cdot 1+0.25\cdot 2=1.25\)个;
Jump指令:2个时钟(译码阶段结束才能得到转移地址,同它进入的指令一定被清除)
平均CPI为:\(1.5\cdot 25\%+1\cdot 10\%+1\cdot 52\%+1.25\cdot 11\%+2\cdot 2\%=1.17\)
所以, N条指令的执行时间为\(1.17\cdot 200N=234N\)(ps)
相关习题
假定最复杂指令所用的组合逻辑分成6部分:A~F,延迟分别为80ps、30ps、60ps、50ps、70ps、10ps。在这些组合逻辑块之间插入流水段寄存器可实现流水线,寄存器延迟为20ps。
理想情况下,以下各方式所得时钟周期、指令吞吐率和指令执行时间各是多少?应在哪里插入流水段寄存器?
(1)插入一个流水段寄存器,得到2级流水线。
C和D之间。时钟周期为190ps,理想情况下,指令吞吐率为每秒钟执行1/190ps=5.26G条指令。每条指令在流水线中执行时间为380ps。
(2)插入两个流水段寄存器,得到3级流水线。
B和C、D和E之间。时钟周期为130ps,指令吞吐率为每秒钟执行1/130ps=7.69G条指令,每条指令在流水线中的执行时间为390ps。
(3)插入三个流水段寄存器,得到4级流水线。
A和B、C和D、D和E之间。故时钟周期为110ps,指令吞吐率为每秒钟执行1/110ps=9.09G条指令,每条指令在流水线中的执行时间为440ps。
(4)吞吐量最大的流水线。
A和B、B和C、C和D、D和E之间,时钟周期为100ps,指令吞吐率为每秒钟执行1/100ps=10G条指令,每个指令的执行时间为500ps。