CPU 的工作可以概括成一个循环:取指令、译码、执行,周而复始。这一章沿着这条循环把 CPU 拆开看:指令按什么节奏执行(指令周期与三级时序),控制信号由谁产生(硬布线控制器与微程序控制器),计划外的事件怎么处理(异常与中断),以及怎么用流水线让多条指令重叠执行。
一、CPU 的功能与基本组成
CPU 按照指令的要求控制计算机各部件协调工作,功能有四个:程序控制、操作控制、时序控制、异常和中断处理。前三个保证指令按正确的顺序、内容和节奏执行,最后一个负责处理执行过程中的意外事件。
CPU 由控制器和运算器组成。
- 控制器:包含程序计数器 PC、存储器地址寄存器 MAR、存储器数据寄存器 MDR、指令寄存器 IR、地址生成逻辑、指令译码器、时序发生器、操作控制器和中断逻辑,最终向外输出一串微操作控制信号序列。
- 运算器:包含 ALU、通用寄存器组和程序状态寄存器 PSW,PSW 中保存 OF、CF、SF、ZF 等条件标志,供分支指令判断使用。
从汇编程序员的角度看,PC、PSW 和通用寄存器是用户可见的,MAR、MDR、IR 是用户不可见的。图 1 把这些部件的归属和可见性完整画在了一张图上。CPU 内部具体包含哪些寄存器,与处理器架构、指令集和实现方法有较大关系。

二、指令执行的一般流程
计算机的本质任务是运行事先编制好、存放在主存中的程序,控制器按照程序对应的机器指令序列逐条执行。CPU 上电复位后,就进入"取指令、指令译码、执行指令"的永久循环:
- 取指令:按 PC 的值从主存取出指令,同时 PC 自动加 1 指向下一条指令;
- 指令译码:分析指令的操作码和地址码。若是分支指令且条件满足,则计算分支目标地址并修改 PC;
- 执行指令:取操作数、执行相应运算、存放运算结果;
- 检查中断请求:有请求则进入中断响应------关中断、保存断点、把中断服务程序入口地址送入 PC,执行完中断服务程序后返回断点。
流程后半段的两个判断------分支是否跳转、有无中断请求------分别对应本章后面控制器设计和异常处理两个主题。

三、指令周期与各阶段的数据流
指令周期指 CPU 从主存取出并执行一条指令所需的全部时间,由取指周期、间址周期、执行周期、中断周期四段组成。间址周期只在指令采用间接寻址时出现,中断周期只在有中断请求时出现。指令周期内部再由 CPU 时钟周期切成更小的步骤,分别完成取指令、取操作数有效地址和执行指令。
实现指令功能需要依次访问的数据序列叫数据流。四个阶段的数据流都围绕同一组固定角色展开:MAR 只与地址总线对接、只走地址;MDR 与数据总线对接、数据可进可出;CU 在每一步发出对应的读或写命令。
取指周期:根据 PC 的值从主存取出指令送入 IR。
- PC 的内容送 MAR,MAR 经地址总线把地址送主存;
- 控制器发出读命令,经控制总线送到主存;
- 主存读出的指令经数据总线进入 MDR;
- MDR 把指令送入 IR;
- 控制器控制 PC 加 1。

间址周期:根据指令的地址码从主存取出操作数的有效地址。形式地址 Ad(IR) 送入 MAR,发读命令,主存读出的结果经数据总线进入 MDR------此时 MDR 中存放的已经是操作数的有效地址。这一阶段的数据流和取指周期几乎同构,只是地址来源从 PC 换成了 Ad(IR)。

执行周期:不同指令的操作不同,可能涉及 CPU 内部寄存器之间的数据传送、对主存(或 I/O)的读写、对 ALU 的操作三类,因此执行周期没有统一的数据流图(图 5)。

中断周期:保存断点、把中断服务程序的入口地址送入 PC。先做 SP←(SP)−1 并送入 MAR,控制器发写命令,把 PC 的值(断点)经 MDR 写入主存中的堆栈,再把中断服务程序的入口地址送入 PC,

四、数据通路
数据通路是数据在各功能部件之间传送的路径。就 CPU 内部而言,指运算器和各寄存器之间的数据传送路径,它在控制信号的控制下工作。
数据通路是连接前后内容的枢纽:上一节的每一步数据流,都要落到具体的数据通路上执行;下一节控制器产生的每个控制信号,作用对象就是数据通路上的传送。数据通路的结构决定了每个微操作要经过哪些路径,也就决定了需要哪些控制信号。
五、控制器的三级时序与三种控制方式
控制器用三级时序把指令周期切成可以安排的小步:状态周期(也叫机器周期)、节拍电位、节拍脉冲。定长指令周期指所有指令的指令周期包含相同数量的状态周期和节拍电位。以图 7 的例子来说:每个指令周期包含 3 个状态周期(取指周期 M_IF、计算周期 M_CAL、执行周期 M_EX),每个状态周期包含 4 个节拍电位 T1~T4,每个节拍电位包含 1 个节拍脉冲(CPU 时钟或其分频信号)。
三级的分工可以用一句话概括:状态周期回答"要干一件什么事",节拍电位回答"这件事分几个步骤",节拍脉冲回答"每个步骤具体在哪个时刻开干"。
按照各部件工作的节奏,控制方式分三种:
- 同步控制:取各部件中最长的操作时间作为标准时间间隔,实现简单,但平均速度受最慢部件拖累;
- 异步控制:没有统一的 CPU 时钟,也没有固定的状态周期和节拍电位,各部件用应答机制握手,速度快但控制复杂;
- 联合控制:以上两种相结合,大部分部件同步、局部异步。

六、时序发生器:用有限状态机产生时序
时序发生器负责产生状态周期信号和节拍电位信号,本质是一个同步时序电路。晶体振荡器产生的脉冲经过时序整形和分频得到节拍脉冲;输入还包括指令译码信号 I1~Im、反馈信息信号 FB1~FBk(运算器的运算状态、I/O 总线的异常或外部中断请求等),以及启动、停止、复位信号;输出是状态周期信号 M1~Mi 和节拍电位信号 T1~Tj,见图 8。设计时要保证节拍电位从第一个节拍开始、到最后一个节拍结束,确保状态周期的完整性。
对定长指令周期的同步控制方式,时序仅与节拍脉冲相关;变长指令周期还会与指令译码信号、反馈信息信号相关。
时序发生器可以按 Moore 型有限状态机 FSM 设计,分四步:先划分状态周期和节拍电位;再构建 Moore 型 FSM,每个状态输出一组状态周期和节拍电位信号(例如取指周期的第一个状态输出 M_IF=1、T1=1,lw/sw/beq 与 add/addi 在译码后进入不同的状态序列);然后列出状态转换表,状态在节拍脉冲的下降沿转换;最后由状态寄存器、次态组合逻辑(FSM)和输出函数组合逻辑构成电路。


七、硬布线控制器
硬布线控制器用于产生微操作控制信号序列,也叫组合逻辑控制器,由逻辑门和触发器构成。如图 10 所示,指令寄存器送出的指令译码信号 I、时序发生器送出的状态周期信号 M 和节拍电位信号 T、外部的反馈信息信号 FB 一起汇入硬布线控制器组合逻辑单元,向外输出 C1~Cn 一列微操作控制信号。每个控制信号都是这四类信号的"与---或"函数:
text
Cn = Σ ( Ii · Mj · Tk · FBk )
含义是:把这条控制信号在哪些指令、哪些状态周期、哪些节拍电位、哪些反馈条件下有效逐项列出,每项内部相与,再对所有有效情况求和(或)。硬布线控制器内部结构相对复杂但速度快,目前 RISC 指令集的处理器广泛采用;组合逻辑单元可以用组合逻辑电路、可编程逻辑阵列 PLA 或 ROM 实现。

三级时序硬布线控制器的设计流程有五步:
- 对指令集中每一条指令执行时的数据通路进行分析,得出每条指令的执行操作流程和每一步所需的控制信号;
- 把每条指令的每个微操作划分到相应状态周期的具体节拍电位上,即对操作控制信号做定时控制;
- 按照同步控制方式(定长或变长指令周期)构造相应的时序发生器;
- 对每个控制信号,分析它在不同指令、不同状态周期、不同节拍电位下是否有效,写出逻辑表达式;
- 用逻辑门、PLA 或 ROM 实现每个控制信号的逻辑表达式,得到硬布线控制器的核心------组合逻辑单元。

现代时序硬布线控制器的设计流程整体相同,差别集中在定时单位上
| 步骤 | 三级时序硬布线控制器 | 现代时序硬布线控制器 |
|---|---|---|
| 微操作定时 | 划分到状态周期的具体节拍电位 | 划分到具体的时钟周期 |
| 时序的构造 | 构造相应的时序发生器 | 以时钟周期为单位画出状态转换图、列出状态转换表,构造有限状态机 FSM |
| 其余步骤 | 分析数据通路、写控制信号逻辑表达式、用逻辑门/PLA/ROM 实现 | 相同 |

八、微程序控制器
硬布线控制器把控制信号"焊死"在组合逻辑里,指令集一变就要重新设计电路。微程序控制器换了一条路,核心思想是模仿程序:程序把机器指令存起来让 CPU 逐条执行,微程序把每条指令需要的控制信号序列预先编好、存进控制存储器,执行时逐条取出。存储程序的思想在这里被复用到了控制信号的生成上。
先理清四个概念:
- 微命令:控制部件发出的最小控制信号;微操作是执行部件收到微命令后完成的最基本操作。微操作分相容性和互斥性:相容性微命令可以在同一个机器周期内并行发出,例如取指时的主存读命令 MemR 和对 PC 的写入控制 PCin;互斥性微命令不允许并行,例如主存读命令 MemR 和写命令 MemW 不能同时有效。
- 微指令:在一个机器周期中,一组实现某一特定操作功能的相容性微命令的集合。
- 微程序:一条指令对应的微指令序列,提前存放在控制存储器 CS 中。
- 微指令周期:从控制存储器取出并执行一条微指令所需的时间。
微程序控制器由四部分组成:
- 控制存储器 CS:存放指令集中各条指令的微程序,字长等于微指令长度,容量取决于所有微程序包含的微指令总数。0 号单元固定存放取指令微程序的第一条微指令,μAR 复位后的初值为 0,所以系统上电就会自动从取指令微程序开始工作。
- 微地址寄存器 μAR:为 CS 提供待读取微指令的地址(微地址),输入来自地址转移逻辑,按时钟脉冲更新锁存。三级时序体制下在状态周期(机器周期)的最后一个节拍结束时触发,现代时序体制下在当前时钟周期结束时触发;若 CPU 中需要时序配合的控制信号是上升沿有效,μAR 的更新就在下降沿触发。
- 微指令寄存器 μIR:暂存从 CS 取出的微指令,是微程序控制器的组成部分,汇编程序员不可见。
- 地址转移逻辑:根据指令的译码情况、外部状态条件、微指令的判别测试字段和下址字段,产生下一条微指令的微地址送给 μAR。

微指令的格式分三个字段:
text
| 下址字段 | 判别测试字段 | 操作控制字段 |
操作控制字段的值经控制总线送到所有执行部件的控制点(如三态门的使能端),控制相关部件执行相应的微操作;判别测试字段用于实现地址转移逻辑;下址字段指出即将读取的下一条微指令在 CS 中的地址。
形成下一条微指令地址的常用方法有两种。下址字段法(断定法)为每条微指令都配上下址字段,顺序执行时下一个微地址直接由下址字段给出,发生转移时由多路选择器 MUX 在微程序入口地址、各分支地址和下址字段之间选择;方式灵活,代价是每条微指令都要为下址字段付出字长。计数器法的微指令不带下址字段,只有判别测试字段和操作控制字段,顺序地址靠 μAR 自身加 1 计数产生,需要跳转时由地址转移逻辑送入转移地址,MUX 的输入中还固定保留取指令微程序的入口地址(0 号单元);微指令可以做得更短,转移安排则受计数器约束。

地址转移逻辑的工作方式(下址字段法见图 15,计数器法见图 16):MUX 的选择控制端由条件判别测试组合逻辑根据判别测试字段 P0~Pk 和外部状态条件 FB 自动生成。P0 位为 1 时,下一条微指令地址取微程序入口查找组合逻辑输出的入口地址,也就是新指令对应微程序的入口;P1~Pk 位用来检测对应的外部状态条件反馈信号,条件满足就在当前微程序内跳转到相应微指令处;P0~Pk 全 0 时,按下址字段顺序执行。每条指令的微程序设计完成后,它在 CS 中的入口地址就是固定的,可以预先列出指令与微程序入口地址的对应关系,由微程序入口查找组合逻辑实现;如果判别测试字段只有 P0 位,MUX 还可以简化成两路选择器,选择端直接来自 P0。


九、异常与中断
异常由 CPU 内部引起,也称为内部中断,按事件性质分三类:
| 类型 | 含义 |
|---|---|
| 故障 | 指令执行异常,如整型溢出、除数为 0。可恢复故障(如缺页)由 OS 处理后重新执行该指令;不可恢复故障(如未定义指令、越权指令)由 OS 终止当前进程 |
| 自陷 | 程序员显式插入的特定指令,核心目的是实现用户态到内核态的安全切换 |
| 终止 | CPU 无法执行的硬件故障 |
外部中断则是外部设备向 CPU 发出的请求(如按键、鼠标单击),请求 CPU 暂停当前正在执行的程序。
中断处理分两个阶段。第一阶段是中断响应周期,操作全部由硬件实现,并且不可被打断,共三步:
- 关中断:临时禁止中断请求,保证中断响应周期的操作以及后续保护现场操作的完整性,确保中断服务程序执行完毕后能返回断点正确执行。单级中断只有在中断返回时才开中断;多级嵌套中断在完成现场保护后就可以通过指令开中断,方便嵌套。
- 保存断点:保存中断服务程序结束后应返回到的、之前被中断的程序中的位置。已经执行完的指令,断点是下一条指令的位置(可能不是顺序指令地址);缺页故障、段错误这类指令没有执行成功的故障异常,断点要保存异常指令本身的 PC 值,便于处理后重新执行。架构上也有差异:x86 由硬件自动把断点压入内存堆栈,靠栈的 LIFO 特性天然支持多级嵌套;MIPS 硬件只把断点存入易被覆盖的 EPC 寄存器,必须由软件在中断服务程序里立即把 EPC 内容转存到内存(如内核栈),否则嵌套发生时新中断会覆盖 EPC,导致原始断点丢失、无法正确返回。
- 中断识别:根据当前的中断请求识别出中断来源,即识别出具体发生了什么中断,并把该中断的中断服务程序入口地址送入 PC。
第二阶段是执行中断服务程序,由软件实现。整个中断处理过程是硬件和软件协同实现的。图 17 汇总了中断响应周期的三步操作和其中容易忽略的细节。

中断响应周期内的操作全部由硬件实现、不可被打断;响应周期结束后,CPU 从当前 PC 取出中断服务程序的第一条指令开始执行,直到中断返回,这部分由软件完成。
中断服务程序 ISR 一般包含四个步骤:
- 保护现场:把中断服务程序中会被改写的任何寄存器(如 PSW、通用寄存器、多级嵌套时的 EPC)压栈到内存堆栈,确保被中断的程序在中断返回后还能正确执行。中断服务程序没有调用者,现场必须由它自己负责保存,这一点与函数调用中由调用者保存寄存器的约定并不完全相同。
- 中断服务:完成该中断所需的操作。例如网卡收到数据帧触发的硬件中断:从网卡缓冲区提取数据帧、CRC 校验、转入内存安全区、解析帧首部、设置"待处理数据帧"标志位、唤醒后台协议栈线程、通知调度器。中断服务遵循"20/80"法则------只完成 20% 的必要工作,80% 转交后台处理。
- 恢复现场:按与压栈相反的顺序,把保护现场时压栈的各寄存器内容出栈恢复。
- 中断返回:使用 eret 指令返回被中断的程序,返回断点并开中断。
对多级嵌套中断,保护现场后应开中断,让本中断服务程序还能被更高优先级中断打断;恢复现场前应关中断,保证恢复过程的完整性。单级中断同时出现多个请求时按优先级顺序处理;嵌套中断遵循优先级抢占规则,高优先级中断可以打断低优先级中断的服务程序。四个步骤连同嵌套情形下开、关中断的位置,图 18 把它们串在了一条流程上。

十、指令流水线
顺序执行时,前一条指令走完全部阶段,下一条指令才开始,各功能部件得不到充分利用。指令流水线的目的是提高 CPU 中各功能部件的并行性和程序的执行效率:把指令周期分成若干功能段后,同一时刻可以有多条指令分别处在不同的功能段中并发执行。
MIPS32 指令流水线分五个功能段:取指(IF)、译码(ID)、执行(EX)、访存(MEM)、写回(WB)。它由单周期处理器的数据通路改造而来:在每两个功能段之间放置流水寄存器(IF/ID、ID/EX、EX/MEM、MEM/WB),锁存相应功能段处理完成的数据或结果,供下一段使用。
控制信号也随流水线逐段传递,并且出现"产生段"与"使用段"的错位:分支跳转控制信号 BranchTaken 在 IF 段使用,却由 EX 功能段的 Branch 信号与 equal 标志位相与得出;寄存器写控制 RegWrite 在 ID 段使用,却由 WB 段产生。它们正是靠流水寄存器一站一站传过去的。图 19 给出了完整的流水线架构和主要控制信号的来源与作用。

十一、流水线冲突
指令重叠后,后一条指令可能要在前一条指令尚未完成时使用同一资源或同一数据,由此产生三类冲突。
结构相关:多条指令在同一个时钟周期争抢同一操作部件,也称资源冲突。解决方法有两种:增加对应的部件;采用独立的指令存储器和数据存储器,避免取指与数据访存的冲突。
控制相关:遇到分支指令或其他会改变 PC 值的指令时,在它之后载入流水线的后续指令可能因为分支跳转而不能进入执行阶段,这些误取指令要被清除(flush)。以 beq 在 EX 段判断分支为例,分支结果出来前已有两条误取指令进入流水线,需要插进两个空操作;把分支判断提前到 ID 段执行(在 ID 功能段增加比较器和地址加法器)后,整体减少 2 个时钟周期。现代 MIPS 处理器多在 ID 功能段执行分支指令,并配合分支延迟槽技术减少分支指令带来的流水线损失。图 20 用两张时空图对比了这两种做法的差别。

数据相关:后一条指令需要用到前一条指令尚未写回的结果。按操作顺序分三种类型:
| 类型 | 语义 | 依赖性质 | MIPS 标准 5 段流水线中是否冲突 |
|---|---|---|---|
| RAW | 写后读 | 真依赖 | 会,正常程序中大量存在 |
| WAR | 读后写 | 反依赖 | 不会,按流水线顺序读(ID 段)早于写(WB 段) |
| WAW | 写后写 | 输出依赖 | 不会,按序写回(WB 段) |

WAR 和 WAW 只有在乱序调度流水线中才可能出现。解决五段流水线里的 RAW 冲突有三种手段:插入气泡(让后一条指令停下来等待)、数据旁路(把上一条指令的结果直接从流水寄存器引到 ALU 输入端),以及利用 CPU 时钟周期的读写时序天然避免。冲突是否发生、怎么处理,与两条指令之间的距离直接相关:
| 指令序列 | 指令距离 | 气泡法 | 数据旁路法 |
|---|---|---|---|
| 相邻 R-R 型 RAW | 0 | 2 个气泡 | 0,旁路路径 EX/MEM → ALU 输入端 |
| 非相邻 R-R 型 RAW(隔 1 条无关指令) | 1 | 1 个气泡 | 0,旁路路径 MEM/WB → ALU 输入端 |
| 远距离 R-R 型 RAW(隔 2 条以上) | ≥2 | 不需要 | 不需要,靠"下跳沿写入、低电平读出"的读写时序解决 |
| 相邻 Load-Use | 0 | 2 个气泡 | 仍需 1 个气泡,配合 MEM/WB → ALU 输入端旁路 |
| 非相邻 Load-Use(隔 1 条) | 1 | 1 个气泡 | 0 |
| 远距离 Load-Use | ≥2 | 不需要 | 不需要 |
Load-Use 是特例:即使采用数据旁路,load 的数据也要到访存段结束才可用,仍需插入 1 个气泡。

十二、总结
这一章可以串成一条线:指令周期给出时间骨架,取指、间址、执行、中断四个阶段由三级时序切成小步;数据通路给出物理路径;控制器在正确的时间点发出正确的控制信号------硬布线用组合逻辑把信号"算"出来,微程序把信号序列存进控制存储器"取"出来;异常与中断机制处理计划外事件,硬件完成不可打断的中断响应,软件完成现场保护与中断服务;流水线把时间骨架重叠起来换取吞吐量,重叠的代价是结构、控制、数据三类冲突,需要用增加部件、清除误取指令、插入气泡和数据旁路来偿还。
分析 CPU 相关的问题时,可以固定问三个问题:这件事发生在指令周期的哪个阶段(时间),数据走哪条路径(空间),由哪个控制信号在哪个节拍打开(控制)。三个问题都有答案,机制就理顺了。
参考资料
- 湖科大教书匠《计算机组成原理微课堂》