第五部分:中央处理器
5.1 CPU的功能与组成
CPU的基本功能
CPU是计算机的核心部件,负责执行程序中的指令。主要功能包括:
- 指令控制:按顺序取出指令,并控制指令的执行流程(包括跳转)。
- 操作控制:产生各种控制信号,指挥运算器、存储器、I/O设备协同工作。
- 时间控制:为每条指令的各个步骤提供正确的时序信号。
- 数据加工:对数据进行算术运算和逻辑运算。
CPU的基本组成
CPU内部主要由两大部分组成:数据通路 和 控制单元。
-
数据通路 数据通路是指令执行过程中数据所经过的路径,包括:
- 算术逻辑单元(ALU):执行算术和逻辑运算。
- 寄存器组:包括通用寄存器(如R0、R1等)、程序计数器(PC)、指令寄存器(IR)、存储器地址寄存器(MAR)、存储器数据寄存器(MDR)、状态寄存器(PSW或标志寄存器)等。
- 内部总线:连接各个部件,用于数据传送。
- 多路选择器:用于选择不同数据来源。
-
控制单元 控制单元负责产生控制信号,指挥数据通路工作。根据实现方式分为:
- 硬布线控制器:用组合逻辑电路产生控制信号,速度快,但复杂指令集难以实现。
- 微程序控制器:用微指令序列(微程序)产生控制信号,灵活性高,但速度较慢。
重要寄存器说明
- PC(程序计数器):存放下一条指令的地址。每次取指后自动增加(指向下一条指令),遇到转移指令时被修改。
- IR(指令寄存器):存放当前正在执行的指令。从内存取出后暂存在这里,供译码使用。
- MAR(存储器地址寄存器):存放要访问的内存单元的地址。
- MDR(存储器数据寄存器):存放从内存读出的数据,或要写入内存的数据。
- PSW(程序状态字):存放条件码(ZF、OF、SF、CF等)和CPU状态(如中断允许位、工作模式等)。
5.2 指令执行过程
计算机执行程序的过程,就是逐条执行指令的过程。每条指令的执行可以分为若干步骤。
经典的五阶段执行过程(不考虑流水线时,单条指令的完整流程)
-
取指(IF,Instruction Fetch)
- 将PC中的地址送入MAR,并发出读内存信号。
- 从内存读出指令,存入MDR,再送入IR。
- 同时,PC自动增加(PC + 指令长度),指向下一条指令。
-
译码(ID,Instruction Decode)
- 控制器对IR中的指令进行译码,确定操作类型和操作数位置。
- 若需要读取寄存器,在此阶段读取(有的设计中放在执行阶段前)。
-
执行(EX,Execute)
- ALU根据控制信号执行操作(加法、逻辑与、比较等)。
- 如果是转移指令,在此阶段计算目标地址并修改PC。
-
访存(MEM,Memory Access)
- 对于读内存指令(LOAD),在此阶段将地址送入MAR,读内存,数据送入MDR。
- 对于写内存指令(STORE),在此阶段将地址送入MAR,数据从寄存器送入MDR,然后写内存。
- 对于ALU指令,此阶段不做任何操作(或空转)。
-
写回(WB,Write Back)
- 将ALU的计算结果或从内存读出的数据写回寄存器组。
注意:不同指令可能不需要全部五个阶段。例如ADD指令不需要访存阶段;STORE指令不需要写回阶段(因为数据已经写入内存)。
单周期处理器 vs 多周期处理器
- 单周期处理器:每条指令在一个固定的时钟周期内完成(所有阶段合并在一个周期内)。时钟周期必须按最慢的指令(如LOAD)来设定,效率低。考研中主要用于理解原理。
- 多周期处理器:每条指令分为多个时钟周期执行(每个阶段一个周期)。不同指令的周期数不同,效率更高。现代处理器实际采用流水线,是多周期的一种改进。
单周期 vs 多周期性能对比: 假设三类指令的耗时如下:
- ALU指令:2ns
- LOAD指令:5ns
- STORE指令:3ns
- 分支指令:2ns
单周期:时钟周期必须设为5ns(最慢指令的耗时),所有指令都在5ns内完成。CPI=1,但时钟周期长。 多周期:可以将CPU内部操作划分为若干个1ns的阶段。ALU指令需2个阶段(2ns),LOAD需5个阶段(5ns),STORE需3个阶段(3ns)。平均CPI>1,但时钟周期短(1ns)。
控制信号的生成
每条指令执行过程中,需要产生一系列控制信号,例如:
- ALU控制信号:选择加法、减法、逻辑与等。
- 寄存器读/写使能信号。
- 多路选择器的选择信号(选择哪条路径的数据)。
- 内存读/写信号。
硬布线控制器通过组合逻辑电路直接产生这些信号;微程序控制器通过读取微指令产生。
5.3 数据通路
数据通路是CPU中数据流动的路径和存储数据的部件集合。理解数据通路是理解指令执行过程的关键。
寄存器传送语言(RTL)
RTL用于描述数据如何在寄存器之间传送。例如:
PC -> MAR:将PC的内容传送到MAR。M[MAR] -> MDR:将MAR指向的内存单元内容读出到MDR。MDR -> IR:将MDR内容传送到IR。R1 + R2 -> R3:将R1与R2相加,结果存入R3。
RTL描述指令执行示例:
以 ADD R1, R2, R3(R1=R2+R3)为例,用RTL描述多周期执行过程:
取指阶段:
MAR <- PC(PC送地址寄存器)MDR <- M[MAR](读内存)IR <- MDR(指令送IR)PC <- PC + 4(PC+指令字长,假设32位指令)
译码阶段:
5. A <- R[IR[20:16]] (读R2到A寄存器)
6. B <- R[IR[15:11]] (读R3到B寄存器)
执行阶段:
7. ALUOut <- A + B (ALU计算R2+R3,结果存暂存器)
写回阶段:
8. R[IR[25:21]] <- ALUOut (结果写回R1)
单总线结构数据通路
所有部件都连接到一条共享的总线上,任何时刻只能有一对部件通过总线传送数据。优点是硬件简单,缺点是速度慢(需要分时使用总线)。
典型的数据传送步骤(例如执行ADD R1, R2,结果存回R1):
- 取指阶段:PC -> MAR(占用总线),读内存,MDR -> IR。
- 译码阶段:IR中的操作码送控制器,同时从IR中提取R1和R2的编号。
- 执行阶段:R1 -> 总线 -> ALU输入A;R2 -> 总线 -> ALU输入B;ALU计算结果 -> 总线 -> 暂存器(或直接写回R1,但需要注意总线冲突)。
- 实际上单总线需要多个时钟周期完成一次ALU运算,因为无法同时读取两个寄存器。
单总线数据通路的时序瓶颈:
单总线结构中,由于每次只能有一个数据源使用总线,ADD指令需要:
- t1: R1 -> 总线 -> ALU输入A
- t2: R2 -> 总线 -> ALU输入B
- t3: ALU输出 -> 总线 -> R1 总共3个时钟周期才能完成一次加法(仅执行阶段)。 这就是单总线结构速度慢的原因——数据传输顺序化了。
多总线结构数据通路
为了支持同时读取多个操作数,CPU内部常采用多条总线(如一条总线连接寄存器输出,另一条连接ALU输出)。现代CPU使用更复杂的转发网络。
多总线优势: 使用双总线(A总线、B总线)时,上述ADD指令可以同时读取R1和R2:
- t1: R1 -> A总线 -> ALU输入A,R2 -> B总线 -> ALU输入B,ALU输出 -> 结果总线 -> R1 一个时钟周期完成,比单总线快3倍。
典型的MIPS多周期数据通路(考研常见模型)
MIPS多周期数据通路包含以下主要部件和连接:
- 指令存储器与数据存储器分开(哈佛结构在数据通路中的体现)。
- ALU有两个输入端,分别来自寄存器堆和扩展后的立即数。
- 寄存器堆有两个读端口和一个写端口(可同时读两个寄存器,写一个寄存器)。
- 多路选择器用于选择ALU的第二个输入是来自寄存器还是立即数。
- PC的更新有多种来源(PC+4、转移目标地址、跳转地址)。
数据通路中的关键路径
关键路径是数据通路中最长的逻辑路径,决定了时钟周期的最小值。例如,LOAD指令经过:PC -> 指令存储器 -> 寄存器堆读 -> ALU(计算地址) -> 数据存储器 -> 寄存器堆写,路径最长。
LOAD指令的关键路径分析(理解CPU时钟周期为何不能太短): 以LOAD指令为例,一个时钟周期内需完成:
- PC -> 指令存储器(读指令)
- 指令译码 -> 寄存器堆(读基址寄存器)
- 基址 + 偏移量 -> ALU计算地址
- 数据存储器(读数据)
- 数据写入寄存器堆
如果采用单周期设计,时钟周期必须大于这5步的延迟之和。而其他简单指令(如ADD不需要访问数据存储器)也只能等这个长周期,导致性能浪费。
5.4 控制器设计
控制器是CPU的"指挥中心",负责根据指令产生正确的控制信号。考研中需要掌握两种控制器设计方法。
硬布线控制器
- 原理:用组合逻辑电路(门电路)直接产生控制信号。输入是IR中的操作码、状态寄存器的标志位、时钟信号等,输出是各种控制信号。
- 实现方式:列出真值表(指令类型 x 状态 -> 控制信号),然后用逻辑门化简实现。
- 优点:速度快(组合逻辑延迟小)。缺点:指令集复杂时,逻辑电路非常复杂,难以修改。
- 适用:RISC处理器(指令简单,控制逻辑规整)。
硬布线控制器的设计思路(了解):
对于一条指令,控制信号可以表示为:Control = f(Opcode, State, Flags)
例如:对于ADD指令在执行阶段,ALUop = 01(加法),RegWrite = 1(写寄存器),ALUSrc = 0(ALU第二输入来自寄存器)。
这些控制信号通过一个"控制信号真值表"确定,然后用逻辑门(AND、OR、NOT)组合实现。
微程序控制器
- 原理:将控制信号编码成微指令,存放在一个只读存储器(控制存储器)中。执行指令时,从控制存储器中读取一系列微指令,每条微指令产生一组控制信号。
- 微指令格式:包含操作控制字段(控制信号)和顺序控制字段(下一条微指令的地址)。
- 微程序:对应一条机器指令的微指令序列。机器指令被译码后,启动对应的微程序。
- 优点:设计规整,易于修改和扩展(只需修改微程序)。缺点:速度较慢(需要从控制存储器读取微指令)。
- 适用:CISC处理器(指令复杂,微程序便于管理)。
微程序控制器的工作流程:
- 取指令:从主存取指令到IR。
- 机器指令译码:操作码送"微地址形成器",生成该指令对应的微程序首地址。
- 取微指令:从控制存储器(ROM)中取出第一条微指令。
- 执行微指令:微指令的操作控制字段产生控制信号,执行一个微操作。
- 顺序控制:根据顺序控制字段确定下一条微指令地址(通常是顺序执行或转移)。
- 重复步骤3-5,直到该机器指令的微程序执行完毕,返回取指微程序。
微程序控制器的类比:就像烹饪时参考菜谱——每道菜(机器指令)由一系列步骤(微指令)组成,菜谱(控制存储器)中记录了所有步骤,厨师(控制器)按顺序执行。
硬布线 vs 微程序对比
| 特性 | 硬布线 | 微程序 |
|---|---|---|
| 实现方式 | 组合逻辑门电路 | 微指令ROM + 微程序控制器 |
| 速度 | 快 | 慢(多一级访存) |
| 修改灵活性 | 难(需改电路) | 易(改ROM内容) |
| 指令集复杂时 | 非常复杂 | 仍可控 |
| 典型应用 | RISC | CISC(如x86) |
5.5 流水线技术
流水线是提高CPU性能的核心技术,将每条指令的执行过程分解为多个阶段,不同指令的不同阶段可以重叠执行。
流水线的基本概念
以经典五级流水线为例:IF(取指)、ID(译码/读寄存器)、EX(执行)、MEM(访存)、WB(写回)。
理想情况下,每个时钟周期可以完成一条指令(即CPI=1),但实际上受各种冒险影响,CPI会略高于1。
流水线的类比:流水线就像汽车装配线——不是等一辆车完全组装好再开始下一辆,而是让不同工位同时工作。第1辆车在第2个工位时,第2辆车已经在第1个工位了。这样每过一段时间(流水线周期)就有一辆车下线。
流水线执行示例(理想情况,无冒险):
| 时钟周期 | IF | ID | EX | MEM | WB |
|---|---|---|---|---|---|
| T1 | I1 | - | - | - | - |
| T2 | I2 | I1 | - | - | - |
| T3 | I3 | I2 | I1 | - | - |
| T4 | I4 | I3 | I2 | I1 | - |
| T5 | I5 | I4 | I3 | I2 | I1 |
| T6 | I6 | I5 | I4 | I3 | I2 |
从T5开始,每个周期完成一条指令。5条指令从开始到结束需要9个周期,而非流水线的25个周期。
流水线的性能指标
- 吞吐率:单位时间内完成的指令数。理想最大吞吐率 = 1 / 时钟周期。
- 加速比:流水线方式相对于非流水线方式的性能提升。理想加速比 = 流水线级数。
- 效率:流水线各阶段的利用率。有停顿时空闲阶段会降低效率。
流水线性能计算示例: 非流水线处理器执行100条指令需要500个时钟周期(每条指令5周期)。 五级流水线处理器执行100条指令需要:5 + (100-1) = 104个时钟周期(首次装入需要5周期,之后每周期完成一条)。 加速比 = 500 / 104 = 4.8(接近理想加速比5)。 但实际中因为有冒险,加速比通常小于理论值。
流水线冒险(Hazard)
冒险是指流水线中因为下一指令无法在下一个时钟周期正确执行而必须停顿的情况。分为三类:
- 结构冒险
- 原因:硬件资源冲突。例如,指令存储器和数据存储器是同一个,取指和访存需要同时访问内存。
- 解决方法:增加硬件资源(如分离指令Cache和数据Cache,即哈佛结构)。
结构冒险示例: 假设只有1个存储器,指令I1在MEM阶段访存,同时I2在IF阶段取指,两个阶段都要访问存储器。 解决方法:插入1个气泡(停顿I2的IF阶段),等待I1的MEM阶段完成。
- 数据冒险
- 原因:一条指令需要用到前面指令的结果,但前面指令还没有写回。
- 典型情况(按发生顺序):
- 写后读(RAW):最常见。ADD R1, R2, R3;SUB R4, R1, R5(SUB需要ADD的结果R1)。
- 读后写(WAR):较少见,在流水线中可能因乱序执行产生。
- 写后写(WAW):也是乱序执行的问题。
- 解决方法:
- 插入气泡(停顿):暂停流水线,等待前面指令写完。简单但降低性能。
- 前推(转发/旁路):将前面指令的ALU结果直接送到下一指令的ALU输入端,不等待写回寄存器。这是最常用的方法,需要硬件支持。
- 编译器调度:重新安排指令顺序,插入不相关指令来避免冒险。
数据冒险完整示例(RAW):
I1: ADD R1, R2, R3 // R1 = R2 + R3
I2: SUB R4, R1, R5 // R4 = R1 - R5,需要I1的结果R1
五级流水线中:
| 周期 | IF | ID | EX | MEM | WB |
|---|---|---|---|---|---|
| T1 | I1 | - | - | - | - |
| T2 | I2 | I1 | - | - | - |
| T3 | - | I2 | I1 | - | - |
| T4 | - | - | I2(等待) | I1 | - |
| T5 | - | - | I2 | - | I1 |
T3时,I1在EX阶段计算R1,但I2在ID阶段就需要R1。如果没有转发,I2必须等待I1的WB阶段完成(T5)才能读R1。 插入2个气泡后:
| 周期 | IF | ID | EX | MEM | WB |
|---|---|---|---|---|---|
| T1 | I1 | - | - | - | - |
| T2 | I2 | I1 | - | - | - |
| T3 | - | I2 | I1 | - | - |
| T4 | - | - | (气泡) | I1 | - |
| T5 | - | - | I2 | (气泡) | I1 |
| T6 | - | - | - | I2 | (气泡) |
如果用转发(前推):I1在EX阶段(T3)的结果直接送到I2的EX阶段(T4),不需要插入气泡。
| 周期 | IF | ID | EX | MEM | WB |
|---|---|---|---|---|---|
| T1 | I1 | - | - | - | - |
| T2 | I2 | I1 | - | - | - |
| T3 | I3 | I2 | I1 | - | - |
| T4 | I4 | I3 | I2(转发I1结果) | I1 | - |
转发使流水线不需要停顿,性能显著提升。
- 控制冒险
- 原因:遇到转移指令(分支、跳转)时,流水线不知道该取哪条下一条指令。
- 解决方法:
- 插入气泡:暂停流水线,直到转移结果确定。分支开销大(例如MIPS中分支延迟槽)。
- 分支预测:猜测是否转移。静态预测(总是预测不转移,或根据操作码预测),动态预测(用分支历史表,准确率高)。
- 延迟分支:编译器将转移后的有用指令放到分支指令之后执行(分支延迟槽),使流水线不空闲。
控制冒险示例:
I1: BEQ R1, R2, target // 如果R1=R2,跳转到target
I2: ADD R3, R4, R5 // 下一条指令(预测不转移)
I3: SUB R6, R7, R8 // target处的指令
如果不使用分支预测(每次遇到分支就停顿): 在EX阶段才知道是否转移,所以需要插入2个气泡(从取指到执行需要2个周期等待)。
| 周期 | IF | ID | EX | MEM | WB |
|---|---|---|---|---|---|
| T1 | BEQ | - | - | - | - |
| T2 | ADD(可能取错) | BEQ | - | - | - |
| T3 | (气泡) | (气泡) | BEQ | - | - |
| T4 | I3(target) | (气泡) | (气泡) | BEQ | - |
使用分支预测(预测不转移): 如果预测正确,不需要停顿;如果预测错误,需要清空已取入的两条指令并重新取指。
流水线中的异常处理
异常(如缺页、除零)会打断流水线。需要清空流水线中已经取出的后续指令,保存当前指令的PC等状态,跳转到异常处理程序。处理完后再恢复流水线。
超标量与动态流水线(简介)
- 超标量:每个时钟周期可以发射多条指令(如4条),需要多个ALU和更复杂的控制逻辑。
- 动态流水线:允许指令顺序与程序顺序不同(乱序执行),进一步挖掘指令级并行。现代高性能处理器(如Intel Core系列)采用此技术。
超标量示例: 一个4路超标量处理器,每个周期最多可以发射(开始执行)4条指令。 如果程序中有足够的指令级并行度,理论吞吐率是单发射处理器的4倍。 例如:这4条指令没有数据依赖关系:
ADD R1, R2, R3
SUB R4, R5, R6
MUL R7, R8, R9
LOAD R10, [R11]
它们可以在同一个周期同时发射到不同的功能单元执行。
💡 记忆技巧:
- 三类冒险:结构冒险(硬件冲突)、数据冒险(数据依赖)、控制冒险(转移指令)。
- 数据冒险三种类型:RAW(真依赖)、WAR(反依赖)、WAW(输出依赖)。记住RAW最常见(A写入,R读取)。
- 冒险解决方法对比:结构冒险加硬件,数据冒险用转发,控制冒险靠预测。
⚠️ 易错点:
- RAW vs WAR:RAW是写后读(必须先写再读,否则读到旧值),WAR是读后写(必须先读再写,否则写覆盖了旧值)。在经典五级流水线中,WAR和WAW很少发生(因为所有指令按顺序写回)。
- 转发只能解决RAW冒险(EX阶段的直接转发),不能解决LOAD指令的RAW(因为LOAD的数据要从MEM阶段才能获得,需要1个气泡)。
- 分支预测错误需要"清空"流水线中后续指令,并且从正确目标重新取指,性能损失显著。
5.6 CPU部分在408中的常见考点
- 指令执行阶段划分:给出一个指令,写出每个阶段的具体操作(用RTL描述)。
- 数据通路分析:给出数据通路图,分析某条指令执行时各控制信号的值(如多路选择器选择哪个输入,ALU执行什么运算)。
- 流水线冒险判断与解决:给出一段指令序列,指出存在哪些数据冒险或控制冒险,并说明如何通过前推或插入气泡解决。
- 流水线性能计算:给定指令数、流水线级数、停顿周期数,计算吞吐率或加速比。
- 单周期与多周期对比:分析各自优缺点。
- 硬布线与微程序对比:简答题常见。
流水线综合考题示例(408真题风格): 以下指令序列在五级流水线(IF, ID, EX, MEM, WB)上执行:
I1: LOAD R1, [R2] // R1 = M[R2]
I2: ADD R3, R1, R4 // R3 = R1 + R4
I3: STORE R3, [R5] // M[R5] = R3
I4: SUB R6, R7, R8 // R6 = R7 - R8
问:(1)哪些指令之间存在数据冒险?(2)如何解决?(3)需要插入多少个气泡?
解: (1)I1写入R1,I2读R1 -> RAW冒险;I2写入R3,I3读R3 -> RAW冒险。 (2)LOAD与ADD之间的RAW:LOAD的MEM阶段才能得到R1,所以即使使用转发,也需要插入1个气泡(LOAD的MEM -> ADD的EX之间插1个周期)。I2与I3之间的RAW:如果使用转发,I2的EX结果可以直接转发给I3的EX,不需要气泡。 (3)总共需要1个气泡(在I1的MEM之后、I2的EX之前插入)。
📌 408考点提示
考查形式:
- 选择题:CPU组成部件识别、流水线冒险的判断、控制器的类型判断。
- 综合题:数据通路中某条指令的控制信号分析(2016年、2020年408真题)。
- 大题:流水线冒险分析及插入气泡/转发设计(2014年、2018年408真题)。
常见命题模式:
- 给出MIPS多周期数据通路图,要求标出某条指令各阶段的多路选择器选择值。
- 给出指令序列,要求指出所有数据冒险,并设计插入气泡或转发的方案。
- 流水线性能计算:给定指令总数、各类冒险的停顿周期数,计算实际CPI和加速比。
学生常犯错误:
- 流水线中LOAD指令后的RAW需要1个气泡(即使有转发),很多学生误以为转发可以完全消除所有气泡。
- PC更新的时序:PC在取指阶段结束后就更新(指向下一条指令),不是在写回阶段。
- 控制信号的作用混淆:例如MemRead和MemWrite不要搞混,ALUSrc选择的是ALU的第二个输入来源。
备考建议:
- 熟练掌握RTL描述指令执行过程(写出每条指令各阶段的寄存器传送操作)。
- 对于流水线冒险,建议画出"流水线时空图"来辅助分析,直观看到每条指令在哪一阶段。
- 理解硬布线和微程序控制的核心区别,不要只背表格——要理解"为什么硬布线快但难以修改"。
第五部分小结
| 主题 | 核心要点 |
|---|---|
| CPU组成 | 数据通路(ALU、寄存器组、总线)+ 控制单元(硬布线/微程序) |
| 指令执行 | 五阶段:IF、ID、EX、MEM、WB;单周期 vs 多周期 |
| 数据通路 | 寄存器传送语言(RTL);单总线/多总线结构 |
| 控制器设计 | 硬布线(组合逻辑,快但复杂);微程序(微指令+ROM,灵活但慢) |
| 流水线 | 五级流水;结构冒险、数据冒险(前推/停顿)、控制冒险(分支预测/延迟槽) |
| 性能指标 | 吞吐率、加速比、效率 |