CPU 的功能和基本结构

CPU 的功能

  1. 指令控制

    完成取指令、分析指令、执行指令的操作,即程序的顺序控制。

  2. 操作控制

    一条指令的功能往往是由若干操作信号的组合来实现的。

    CPU 管理并产生由内存取出的每条指令的操作信号,把各种操作信号送往相应的部件,从而控制这些部件按指令的要求进行动作。

  3. 时间控制

    严格控制各种操作信号的出现时间、持续时间及出现的时间顺序。

  4. 数据加工

    对数据进行算术和逻辑运算。

  5. 中断处理

    对计算机运行过程中出现的异常情况和中断请求进行处理。

控制器的功能

整个系统的指挥中枢。

负责协调并控制计算机各部件执行程序的指令序列,包括取指令、分析指令、执行指令(基本功能是执行指令,执行指令就是发出有关操作控制信号)。

在控制器的控制下,运算器、存储器和输入/输出设备等功能部件构成一个有机的整体,根据指令的要求指挥全机协调工作。

运算器的功能

数据加工处理中心。

运算器接收从控制器送来的命令并执行相应的动作,对数据进行加工和处理(算术运算/逻辑运算/条件测试)。

CPU 的基本结构

CPU 主要由 运算器控制器 两大部分组成。

CPU 结构的其他分法:

  • 数据通路 + 控制部件
  • ALU + 寄存器 + CU + 中断系统

随着超大规模集成电路技术的发展,更多的功能逻辑被集成到 CPU 中,包括 Cache、MMU、浮点运算逻辑、异常和中断处理逻辑等,因而 CPU 的内部组成越来越复杂,甚至可以在一个 CPU 芯片中集成多个处理器核。但不管 CPU 多复杂,它最基本的部件是数据通路和控制部件。

运算器的结构

算术逻辑单元 ALU (Arithmetic Logic Unit)

主要功能是进行算数/逻辑运算,也可以实现左移或右移的移位操作。

通用寄存器组 GPRs (General Purpose Registers)

可编程指定多种功能,用于存放操作数(包括源操作数、目的操作数、中间结果)和各种地址信息等。

位数与机器字长相等。

在指令中要指定寄存器的编号,才能明确是对哪个寄存器进行访问。

本身不一定具有计数逻辑与移位逻辑。

在大多数处理机中,有 8 ~ 32 个通用寄存器,在 RISC 结构的计算机中可超过 100 个。

IA-32 中的 8 个通用寄存器:

除 EBP 和 ESP 外,其他几个寄存器的用途比较任意。

累加寄存器 ACC (Accumulator)

属于通用寄存器,用于暂时存放 ALU 运算的结果信息,可以作为加法运算的一个输入端(EAX 的 A 即 Accumulator)。

程序状态字寄存器 PSW (Program Status Word)

也叫标志寄存器 FLAGS,保留由算术/逻辑运算指令或测试指令的结果而建立的各种状态信息,如溢出标志 OF、符号标志 SF、零标志 ZF、进/借位标志 CF 等。

每个标志位通常由一位触发器来保存,这些标志位组合在一起称为程序状态字。

这些信息参与并决定微操作的形成,比如条件转移指令执行时所依据的条件就来自 PSW。

暂存寄存器

暂存从数据总线或通用寄存器读来的数据,该数据不能存放在通用寄存器中,以防破坏通用寄存器原有内容。

对应用程序员透明。

😮单总线数据通路中的 ALU 需要配合暂存器使用:由于单总线同一时间内只能有一个操作数,且 ALU 本身内部没有存储功能的组合电路,而只有两个操作数同时出现在 ALU 的两个输入端,ALU 才能执行运算。因此需要在 ALU 的一个输入端加上暂存器,先把一个操作数暂存在暂存器中(当然两个输入端都设置一个暂存器也是可以的)。另外 ALU 的输出端也不能直接与内部总线相连,否则其输出又会通过总线反馈到输入端,影响运算结果,所以在 ALU 输出端还需要加一个暂存器。

移位寄存器

不但可用来存放操作数,而且在控制信号的作用下,寄存器中的数据可根据需要向左或向右移位。

计数器 CT

控制乘除运算的操作步数。

貌似不是寄存器?

控制器的结构

程序计数器 PC (Program Counter) / 指令指针寄存器 IP (Instruction Point)

存放下一条指令在主存中的地址(有效地址)。

有自增功能(因为程序中指令通常是顺序执行的);当遇到转移类指令时,PC 的新值由指令计算得到。

PC 通常可以使用字节地址或字地址,其位数取决于存储器的容量和指令字长:

  • 若 PC 和主存储器均按字节编址,则 PC 的位数 = 主存储器地址线数 = MAR 位数。

  • 若用字地址表示指令地址、主存储器按字节编址,则这种情况下指令必须采用按边界对齐的方式存放,此时 PC 的位数 = 存储器地址位数 - $\log_2(\text{指令字长的字节数})$。

可知,PC 位数至少为 $\log_{2}{\frac{存储器容量}{指令字长}}$。

指令寄存器 IR (Instruction Register)

存放现行指令。

位数等于指令字长。

存储器地址寄存器 MAR

用于存放要访问的主存单元的地址(物理地址)。

位数等于主存储器地址线数,它反映了最多可寻址的存储单元的个数。

存储器数据寄存器 MDR

用于存放向主存写入的信息或从主存读出的信息。

位数等于数据字长,通常也等于存储字长。

指令译码器 ID (Instruction Decoder)

对 IR 中的操作码字段进行分析解释,产生相应的译码信号提供给微操作信号发生器。

时序系统

用于产生各种时序信号,它们都由统一时钟(CLOCK)分频得到。

以时钟脉冲为基础,产生不同指令对应的周期、节拍、工作脉冲等时序信号,以实现机器指令执行过程的时序控制。

微操作信号发生器

综合时序信号、指令译码信号和执行部件反馈的条件标志(即 PSW 的内容)等,产生控制整个计算机系统所需的各种控制信号,其结构有组合逻辑型(硬布线控制器)和存储逻辑型(微程序控制器)两种。

也可以说 CPU 控制器主要由三个部件组成:PC、IR、操作控制器/控制单元 CU。

CPU 的寄存器

分类

  1. 用户可见的寄存器(用户可编程)

    可对这类寄存器编程,以通过使用这类寄存器减少对主存储器的访问次数。

    如 GPRs、PC、PSW、移位寄存器。

  2. 用户不可见的寄存器(用户不可编程)

    不可对这类寄存器编程,它们被控制部件使用,以控制 CPU 的操作。

    如 IR、MAR、MDR、暂存寄存器。

专用寄存器

CPU 的专用寄存器有:PC、PSW、IR、MAR、MDR。

其中,PC 和 PSW 虽然是用户可见寄存器,但是:

  • 机器指令中不能显式地使用 PC,PC 的值是自增的,或者是由转移类指令设置的。
  • 标志寄存器中的内容是执行指令的过程中,CPU 根据指令执行的结果生成的各种标志信息,用户不能直接修改。

指令执行过程

指令周期

指令周期

CPU 从主存中取出并执行一条指令所需的全部时间。

每个指令周期一定大于或等于一个 CPU 时钟周期。时钟周期是 CPU 的最小时间单位。

机器周期 / (基本)工作周期 / CPU 周期

在(同步控制的)计算机中,常把一条指令的执行过程划分为若干个阶段,每一个阶段完成一项工作。每一项工作称为一个基本操作(相对完整的操作),完成一个基本操作所需要的时间称为机器周期。

对于定长机器周期,一个机器周期通常等于一个存取周期(或者说,通过一次总线事务访问一次主存或 I/O 的时间)。这么做是因为 CPU 内部操作的速度很快,而 CPU 访存一次时间较长。

取址周期、间址周期、执行周期、中断周期可以说是机器周期的四种类型,但这不意味着它们的长度就为一个机器周期(虽然大多数时候是)。可以记为,一个机器周期的长度通常等于一个存取周期,一个执行阶段需要访存几次就需要几个机器周期。

时钟脉冲信号 / 工作脉冲

控制器的最小时间单位,起定时触发作用。

由机器脉冲源发出的脉冲信号经整形和分频后形成的。

时钟脉冲信号的宽度称为时钟周期,时钟周期的倒数为机器主频。

时钟周期 / 节拍 / T 周期

计算机工作的最小时间周期,CPU 操作的最基本单位。

时钟周期以相邻状态单元间组合逻辑电路的最大延迟为基准确定。

指令周期 vs 机器周期 vs 时钟周期

指令周期常常用若干机器周期来表示。

每个指令周期内机器周期数可以不等,即不同指令的指令周期可能不同:

每个机器周期内的节拍数也可以不等:

机器周期和时钟周期不一定谁有若干个谁,比如单周期处理器的指令周期只有一个时钟周期(不包括中断周期)。只能从 指令周期有几个时钟周期 + 指令周期有几个机器周期 来看。

一个指令周期一定大于等于一个时钟周期。

每个执行阶段内的机器周期数也可以不等。比如,定长机器周期,一个机器周期取一个存取周期,而指令字长一般取存储字长的整数倍,若指令字长等于存储字长的 2 倍,则需要 2 次访存,因此取指周期等于机器周期的 2 倍。

指令周期流程

取指周期:取指令 → PC + “1”(→ 指令译码)。当遇到转移指令等改变执行顺序的指令时,在 PC + “1” 会重新计算并更新 PC 值。

间址周期(若有):获取操作数的有效地址。

执行周期:完成取操作数、执行运算、存操作数的任务。

中断周期(若有):即中断响应阶段(中断隐指令)。当 CPU 采用中断方式实现主机和 I/O 设备的信息交换时,CPU 在每条指令执行结束前(执行周期后),都要发出中断查询信号,若有中断请求,则 CPU 进入中断响应阶段。

👽取指周期和执行周期是每个指令都有的工作周期(空指令?)。

上述 4 种工作周期都有 CPU 访存操作,但目的不同:

  • 取址周期:取指令。

  • 间址周期:取操作数有效地址。

  • 执行周期:取操作数。

  • 中断周期:保存程序断点。

冯·诺依曼计算机根据指令周期的不同阶段来区分从存储器取出的是指令还是数据。

控制器可区分存储单元中存放的是指令还是数据(数据通路不能)。

为区分不同的工作周期,在 CPU 内设置了 4 个标志触发器 FE、IND、EX、INT,分别对应取指(Fetch)、间址(Indirect)、执行(Execute)、中断(Interrupt) 4 个周期(Cycle),并以 “1” 状态表示有效,分别由 1 → FE、1 → IND、1 → EX、1 → INT 这 4 个信号控制。

指令周期的数据流

数据流:根据指令要求依次访问的数据序列。

在指令执行的不同阶段,要求依次访问的数据序列是不同的。

对于不同的指令,它们的数据流往往也是不同的。

取指周期数据流

任务:根据 PC 中的内容从主存中取出指令代码并存放在 IR 中。

不同长度的指令,其取指操作可能是不同的(访存次数可能不同)。

以指令字长 = 存储字长的指令为例(即取指只需访存一次,取指周期长度 = 一个机器周期):

① ~ ③:PC 中的指令地址(经过 MMU 转换为物理地址后)先送 MAR,再经地址总线送主存。

④ ~ ⑤:CU 发出读命令经控制总线送主存。

⑥ ~ ⑧:指令代码从主存经数据总线先送 MDR,再从 MDR 送入 IR。

⑨:CU 发出控制信号使 PC + “1”。

取指操作是控制器自动进行的,不需要得到相应的指令。

间址周期数据流

任务:取操作数有效地址。

具体的数据流向取决于寻址方式。以一次间接寻址为例:

① ~ ③:指令中的地址码 Ad(IR/MDR)(经过 MMU 转换为物理地址后)先送 MAR,再经地址总线送主存。

④ ~ ⑤:CU 发出读命令经控制总线送主存。

⑥ ~ ⑦:操作数有效地址从主存经数据总线送 MDR。

💇数据寻址,指令地址码可从 IR 或 MDR 中获取。因为在之前的取指周期中,指令字是先经 MDR 再送 IR,在随后的间址周期,MDR 中存放的仍是该指令字。

执行周期数据流

任务:一般是取操作数和根据 IR 中的指令字的操作码通过 ALU 操作产生执行结果。

不同指令的执行周期操作不同,因此没有统一的数据流向。

中断周期数据流

任务:处理中断请求,即中断响应。

这里只考虑保存 PC 到内核栈中:

① ~ ⑧ 保存 PC 值到内核栈。

​ ① ~ ③ CU 先控制将 SP 减 “1” 再送 MAR,然后经地址总线送主存。

​ ④ ~ ⑤ CU 发出写命令经控制总线送主存。

​ ⑥ ~ ⑧ PC 值先送 MDR,再由 MDR 经数据总线送存储器。

⑨ CU 将取到的中断服务程序入口地址送 PC。

因为只是数据流,故这里没有说明关中断(中断允许位清 0)和引出中断服务程序入口地址(软件查询法/硬件向量法)的过程。

指令执行方案

一个指令周期通常要包括几个执行步骤,每个步骤完成指令的一部分功能,几个依次执行的步骤完成这条指令的全部功能。不同处理器采用不同的方案来安排指令的执行步骤。

单周期处理器

最简单的非总线结构处理器是单周期处理器。

对所有指令都选用相同的执行时间来完成,每条指令都在一个时钟周期内完成,即 CPI = 1。

指令之间串行执行,即下一条指令只能在前一条指令执行结束后才能启动。

时钟周期取决于执行时间最长的指令的执行时间,导致时钟频率较低。对于那些本来可以在更短时间内完成的指令,要使用这个较长的周期来完成,会降低整个系统的运行速度。

在指令执行过程中控制信号不变

不能使用单总线数据通路:单总线一个时钟周期内只允许一次数据传输,无法在一个时钟周期内完成一个指令的所有数据传输。

必须有独立的指令存储器和数据存储器:不能在一个时钟周期内对一个(单端口)存储器进行两次不同的存取(上升沿/下降沿)。

多周期处理器

对不同类型的指令选用不同的执行步骤来完成。指令需要几个周期就为其分配几个周期,因此可选用不同个数的时钟周期来完成不同指令的执行过程。

多周期 CPU 至少需要 2 个时钟周期才能执行一条指令,即 CPI > 1(王道 P216 选择 15)。

执行各条指令的机器周期数可变,各机器周期的长度可变。

指令之间仍是串行执行。

需要更复杂的硬件设计。

单周期 CPU vs 多周期 CPU

  • 单周期 CPU 执行任何指令的时间不一定都会小于多周期 CPU。

    这取决于单周期 CPU 和多周期 CPU 的时钟周期的长短,以及该指令在多周期下所需的时钟周期数。

  • 通常单周期 CPU 的时钟周期比多周期 CPU 的时钟周期长。

  • 多周期 CPU 的 CPI(> 1)大于单周期 CPU 的 CPI(= 1)。

  • 在一条指令的执行过程中:

    单周期 CPU 的每个控制信号保持不变,每个部件只能使用一次;

    多周期 CPU 的控制信号可能会改变,同一个部件可使用多次。

  • 单周期 CPU 部件冗余大,利用率低,多周期 CPU 则相反。

流水线处理器

采用指令之间并行执行的方案,其追求的目标是力争在每个时钟周期完成一条指令的执行过程(只在理想情况下才能达到该效果,此时 CPI = 1)。

在每一个时钟周期启动一条指令,尽量让多条指令同时运行,但各自处在不同的执行步骤中。

一个简单的单周期数据通路实现

基于 ARMv8 指令集的子集 LEGv8。

32 个通用寄存器。

字的长度为 32 位,机器字长 64 位,指令字长 32 位,存储字长 64 位。

指令存储器按字节编址。

指令寻址中的跳跃寻址基于分支指令本身(而非分支指令的下一条指令)。

操作数寻址方式为基址寻址 EA = (BR) + A。

涉及的三种指令类型及其格式

  • R 型指令(算术逻辑指令)

    读两个寄存器并对这两个寄存器的内容执行 ALU 操作,然后将结果写回寄存器。

    Rn、Rm 源操作数,Rd 目的操作数,shamt 用于移位(暂不考虑)。

  • 取数指令和存数指令

    load 指令:LDUR X1, [X2, offset_value]

    store 指令:STUR X1, [X2, offset_value]

    Rn 寄存器作为基址。对于 load 指令,Rt 是目的寄存器;对于 store 指令,Rt 是待存入数据所在的寄存器。

    偏移字段为 9 位带符号值。

  • 分支指令(比较为 0 指令 CBZ)

    CBZ 指令格式:CBZ X1, offset

    Rt 是源寄存器,用于测试值是否为 0。

    偏移字段为 19 位带符号值,基于字长,而指令存储器按字节编址,故偏移量需左移 2 位。

符号扩展单元

一个 32 位的指令作为输入,但只需对指令中的 9 位或 19 位进行扩展。

选取 9 位用于存储数据,选取 19 位用于 CBZ 指令(比较为 0 分支)。

多级译码

主控制单元生成 ALUOp 作为 ALU 控制单元的输入,再由 ALU 控制单元生成真正的 ALU 控制信号。

多级控制可以减小主控制单元的规模。多个小控制单元也可减少控制单元的延迟,这对决定时钟周期的长短非常关键。

LEGv8 ALU 定义了 6 种有效输入,由 4 位控制信号选择:

使用一个小的控制单元即可生成 4 位 ALU 控制信号,该单元输入为指令的操作码字段和 2 位的 ALUOp 控制字段。

ALUOp 控制位将六个指令分为三部分:

  • 00:访存指令需要的加法。
  • 01:CBZ 需要的传递输入 b。
  • 10:依赖于指令操作码字段的操作。

控制信号

共有 9 位控制信号:7 个 1 位控制信号(4 个 Mux、寄存器写控制、数据存储单元读写控制)和 1 个 2 位 ALUOp 控制信号。

  • 所有的多路选择器都是两个输入端,因此每个 Mux 都需要一条单独的控制线。

  • 寄存器组的读输出总是对应于读寄存器号,故寄存器读操作不需要读控制信号。

  • PC 不需要写控制信号,因为 PC 在每个时钟周期结束时都被写入一次。

  • 所有的状态单元都有一个隐含输入 —— 时钟信号,用于写操作的控制。

7 个 1 位控制信号的功能:

PCSrs 信号是将来自控制单元的 Branch 信号和 ALU 的零输出信号相与得到的,即在指令为 CBZ 且 ALU 的零输出有效时被置位。

除 PCSrc 外,其它信号都可由控制信号根据指令的操作码直接生成。

主控制单元根据指令(操作码)设置的 9 位控制信号(注意这里的是 Branch 信号而非 PCSrs 信号):

捋一下:

  • opcode → 主控制单元 → 9 位控制信号
  • opcode + ALUOp → ALU 控制单元 → 4 位 ALU 控制信号

数据通路的功能和基本结构

不管 CPU 内部结构多么复杂,它都可视为由 数据通路(Data Path)控制部件(Control Unit) 两大部分组成。

数据通路的功能

数据通路

通常将指令执行过程中数据所经过的路径(包括路径上的部件)称为数据通路。

ALU、通用寄存器、状态寄存器、Cache、异常和中断处理逻辑等都是指令执行过程中数据流经的部件,都属于数据通路的一部分。

数据通路描述了信息从哪里开始,中间经过哪些部件,最后被传送到哪里。

执行部件/功能部件(excution unit/function unit)

数据通路中专门进行数据运算的部件。

控制部件

控制部件就是 CPU 的控制器。

数据通路由控制部件进行控制,控制部件根据每条指令功能的不同生成对数据通路的控制信号,并正确控制指令的执行流程。

数据通路不包括控制部件。

数据通路的分类

  • CPU 内部数据通路

    CPU 内部的数据传送通路,用于在寄存器之间或寄存器与 ALU 之间传送数据。

    宽度一般等于机器字长。

  • CPU 外部数据通路

    借助系统总线,将寄存器(MAR 和 MDR)与存储器和 I/O 模块连接起来。

    宽度等于数据总线位数。

数据通路的功能

实现 CPU 内部的运算器与寄存器及寄存器之间的数据交换(内部数据通路)。

数据通路的组成

组成数据通路的元件

  • 组合逻辑元件/操作元件

  • 时序逻辑元件/状态元件/存储元件

连接元件的方式

  • 总线连接方式

    当 CPU 内部采用总线连接方式时,总线上信号流动的原则如下:

    每个时刻只有一个器件发出信息(否则会导致总线冲突),每个时刻可以有一个或多个器件接受信息。

  • 分散连接方式

组合逻辑元件/操作元件

组合逻辑元件的输出只取决于当前的输入。若输入一样,其输出也一样。

组合电路不含存储信号的记忆单元,输入和输出之间无反馈通路,信号是单向传输的。

组合电路的定时不受时钟信号的控制,所有输入信号到达后,经过一定的逻辑门延迟,输出端的值被改变,并一直保持其值不变,直到输入信号改变。

数据通路中常用的组合逻辑元件有多路选择器 MUX、加法器 Adder、算术逻辑部件 ALU、译码器 Decoder、三态门等(图中虚线表示控制信号)。

译码器、多路选择器、三态门的应用:

  • 译码器可用于操作码或地址码译码,$n$ 位输入对应 $2^n$ 中不同的组合,因此有 $2^n$ 个不同输出。

  • 多路选择器 MUX 需要控制信号 Select 来确定哪个输入被输出。

  • 三态门可视为一种控制开关,由控制信号 EN 决定信号线的通断,当 EN = 1 时,三态门被打开,输出信号等于输入信号;当 EN = 0 时,输出端呈高阻态(隔断态),所连寄存器与总线断开。

时序逻辑元件/状态元件/存储元件

具有存储功能,输入状态在时钟控制下被写到电路中,并保持电路的输出值不变,直到下一个时钟到达。

任意时刻的输出不仅与该时刻的输入有关,还与该时刻以前的输入有关,因而时序电路必然包含存储信号的记忆单元。

时序电路必须在时钟节拍下工作。输入端状态由时钟决定何时被写入。在时序逻辑元件中存储的所有值仅在时钟边沿触发更新(上升沿/下降沿)。

输出端状态随时可以读出。

数据通路中常用的状态元件:锁存器、触发器、寄存器、主存(外部数据通路)。

寄存器由锁存器或触发器构成,由 N 个锁存器或触发器可以构成 N 位寄存器。

时钟策略

时钟策略规定了信号可以读出和写入的时间,用以确定数据相对于时钟何时有效和稳定的方法。

边沿触发

边沿触发检测的是电平变化,时钟边沿意味着从低到高或从高到低的跳变,因此边沿触发包括上升沿触发和下降沿触发(也存在双沿触发)。

所有的组合逻辑必须从状态单元接收输入(前一个时钟周期写入的数据),并将输出写入状态单元中(可在下一个时钟周期使用)。

边沿触发允许在一个时钟周期内同时读写一个单元而不会因竞争而导致不确定的数据值,即可在同一时钟周期内读写同一存储单元:读出之前写入的内容,写入的内容在下一时钟周期才可读。边沿触发的时钟策略下,一个时钟周期内不可能出现反馈。在有效的时钟边沿导致状态变化之前,状态单元的输入信号必须达到稳定(即状态单元的值保持不变直到时钟沿到来)。这需要时钟周期足够长。

若一个状态单元在每个有效的时钟边沿都进行写入时,不必给出控制信号(如单周期处理器中的 PC);若一个状态单元不是每个周期都进行更新,那么就需要一个显式的写控制信号。

边沿触发可以实现对瞬间信号的响应,适合于控制快速变化的动作。

在时序逻辑单元中存储的所有值仅在时钟边沿更新。

电平触发

电平触发是在高或低电平保持的时间内触发,检测的是电平值,包括高电平触发和低电平触发。

电平触发可以在一段时间内保持输出信号不变(只要输入信号保持稳定,就会一直触发输出信号),因此适合于控制长时间持续的动作。

边沿触发和电平触发基本就是触发器和锁存器的区别。

数据通路的基本结构

数据通路结构直接影响 CPU 内各种信息的传送路径,数据通路不同,指令执行过程的微操作序列的安排也不同,它关系着微操作信号形成部件的设计。

CPU 内部单总线方式

将 ALU 及所有寄存器的输入端和输出端都连接到一条内部公共总线上,称为单总结构的数据通路。

结构简单,但数据传输存在较多的冲突现象。一个时钟内只允许传一个数据,性能较低😟

单周期处理器不能采用单总线方式,因为单总线将所有寄存器都连接到一条公共总线上,一个时钟内只允许一次操作,无法完成一条指令的所有操作。

rs、rd 分别为所读、写的通用寄存器编号;Y 和 Z 为暂存器;FR 为标志寄存器,用于存放 ALU 所产生的标志信息。带箭头的虚线表示控制信号。

能输出到总线的部件均通过一个三态门与内部总线相连,用于控制该部件与内部总线之间数据通路的连接和断开。

CPU 内部多总线方式

CPU 中有两条或更多的总线时,构成双总线结构或多总线结构。

将 ALU 及所有寄存器的输入端和输出端都连接到多条公共通路上,能同时在多个总线上传送不同的数据,相较单总线方式效率有所提高。

专用数据通路方式

根据指令执行过程中的数据和地址的流动方向安排连接线路,避免使用共享的总线。

性能较高,基本不存在数据冲突现象,但结构复杂,硬件量大,不易实现。

专用数据通路方式下取指周期的数据传送流程和控制信号:

(PC) → MAR C0 有效

(MAR) → 主存 C1 有效

1 → R 控制单元向主存发送读命令

M(MAR) → MDR C2 有效

(MDR) → IR C3 有效

(PC) + 1 → PC

最后也可以把译码算上:Op(IR) → CU C4 有效

数据通路的操作举例

以下图给出的单总线数据通路为例,介绍一些常见操作的流程及控制信号。

(PC) 有时可简写为 PC。本笔记均未采用这种简写。

做题时要以题目提供的控制信号为准。

寄存器之间的数据传送

以把 PC 内容送至 MAR 为例:

1
2
(PC) → Bus    PCout有效
Bus → MAR MARin有效

也可写为:

1
(PC) → Bus → MAR  PCout和MARin有效

Bus 指片内总线,可省略不写,故也还可写为:

1
(PC) → MAR    PCout和MARin有效

从主存读取数据

以 CPU 从主存取指令为例:

1
2
3
4
5
6
(PC) → MAR        PCout和MARin有效
1 → R CU发读命令
MEM(MAR) → MDR MDRinE有效 #E=External?注意这里不是经过Bus,而是系统总线中的数据总线.
(PC)+1 → PC PCin有效
(MDR) → IR MDRout和IRin有效
OP(IR) → CU/ID IRout有效 #一般省略

有的题目不提供 MDRinE、MDRoutE,统一使用 MDRin、MDRout。

有的题目提供 MARout,读写内存时需要使用该信号。

以一次间接寻址为例:

1
2
3
4
Ad(IR) → MAR      AdIRout和MARin有效
1 → R CU发读命令
MEM(MAR) → MDR MDRinE有效
(MDR) → Ad(IR) MDRout和IRin有效

将数据写入主存

以将寄存器 R1 的内容写入寄存器 R2 所指的主存单元为例:

1
2
3
4
(R1) → MDR          R1out和MDRin有效
(R2) → MAR R2out和MARin有效
1 → W CU发写命令
(MDR) → MEM(MAR) MDRoutE有效

执行算数或逻辑运算

以累加器型加法指令、直接寻址为例:

1
2
3
4
5
6
Ad(IR) → MAR       AdIRout和MARin有效  #操作数有效地址也可从MDR中取,但前提是此时MDR中保存的是指令字.
1 → R CU发读命令
MEM(MAR) → MDR MDRinE有效
(MDR) → Y MDRout和Yin有效
(ACC) + (Y) → Z ACCout和ALUin有效,CU向ALU发送加命令
(Z) → ACC Zout和ACCin有效 #(Z) → Bus → ACC

单总线结构下 ALU 需要配合暂存器使用:

  • 暂存器 Y 的内容在 ALU 的左输入端始终有效(因此不需要 Yout 控制 Y 的输出)。
  • 暂存器 Z 暂存 ALU 输出的运算结果(不需要 Zin 控制 Z 的输入)。

修改程序计数器的值

假设转移指令 JMP addr,addr 为目标转移地址,实现将 IR 中的地址字段写入 PC:

1
Ad(IR) → PC    AdIRout和PCin有效

控制器的功能和工作原理

控制器的结构和功能

计算机硬件系统的五大功能部件及其连接关系

画线框内是控制器部件,组成为 PC + IR + CU,省略了 MDR 和 MAR。
PC/SP → MAR → 地址总线,数据总线 → MDR → GPRs/IR/ALU。

控制器的主要功能

指令控制、操作控制、时间控制、中断处理。

  1. 从主存中取出一条指令,并指出下一条指令在主存中的位置。
  2. 对指令进行译码或测试,产生相应的操作控制信号,以便启动规定的动作。
  3. 指挥并控制 CPU、主存、输入和输出设备之间的数据流动方向。

控制器的设计

根据控制器产生微操作控制信号方式的不同,控制器可分为:

  • 硬布线控制器/组合逻辑控制器
  • 微程序控制器

两类控制器中的 PC 和 IR 是相同的,但确定和表示指令执行步骤的办法以及给出控制各部件运行所需要的控制信号的方案是不同的。

硬布线控制器

硬布线控制器由复杂的组合逻辑门电路和一些触发器构成,因此又称为组合逻辑控制器。

基本原理

根据指令的要求、当前的时序及外部和内部的状态,按时间的顺序发送一系列微操作控制信号。

特点

  • 执行速度很快:使用纯硬件实现控制。
  • 扩充指令较困难:扩充一条新的指令,控制器的设计就需要大改。
  • 一般用于 RISC:指令越多,设计和实现就越复杂。

硬布线控制单元图

以下是本节对 CU 逻辑的简化:

  • 将存放在 IR 的 $n$ 位操作码经过移码电路产生 $2^n$ 个输出,每种操作码对应一个输出送至 CU。

  • 将指令译码器和节拍发生器从 CU 分离出来。

CU 的输入信号来源

  1. 经指令译码器译码产生的指令信息

    现行指令的操作码决定了不同指令在执行周期所需完成的不同操作,它与时钟配合产生不同的控制信号。

  2. 时序系统产生的机器周期信号和节拍信号

    一个时钟脉冲使控制单元发送一个操作命令或一组需要同时执行的操作命令。

  3. 来自执行单元的反馈信息

    不止是运算器中的 PSW,还有 ACC 的符号位。另外还接收来自系统总线(控制总线)的控制信号,如中断请求、DMA 请求等。

前两者是主要因素。

CU 的输出去向

  1. CPU 内部
  2. 外部控制总线

时序控制

时钟周期

用时钟信号控制节拍发生器,产生的每个节拍的宽度正好对应一个时钟周期。

在每个节拍内机器可完成一个或几个需同时执行的操作

机器周期

机器周期可视为所有指令执行过程中的一个基准时间。

以完成最复杂指令功能的时间为准:不同指令、不同类型的机器周期的时间长短可能不同,但访问一次存储器的时间是固定的且比 CPU 中的操作时间长得多,所以通常以主存工作周期(即存取周期)作为机器周期

再次强调:在存储字长 = 指令字长的前提下,取指周期长度 = 一个机器周期。

指令周期

CPU 从主存中取出并执行一条指令的时间。

CPU 控制方式

控制单元控制一条指令执行的过程,实质上是依次执行一个确定的微操作序列的过程。

同步控制方式

系统有一个统一的时钟,所有的控制信号均来自这个统一的时钟信号。

通常以最长的微操作序列和最繁琐的微操作作为标准,采取完全统一的、具有相同时间间隔和相同数据的节拍作为机器周期来运行不同的指令。

优点:控制电路简单。

缺点:运行速度慢。

异步控制方式

不存在基准时标信号,各部件按自身固有的速度工作,通过应答方式进行联络。

优点:运行速度快。

缺点:控制电路比较复杂。

联合控制方式

介于同步、异步之间的一种折中,对各种不同的指令的微操作实行大部分采用同步控制、小部分采用异步控制的办法。

设计步骤

  1. 列出微操作命令的时间表

    1)分析每个阶段的微操作序列(取指、间址、执行、中断),罗列出所有指令在各个阶段的微操作序列。

    2)选择 CPU 的控制方式:定长机器周期 or 不定长机器周期?每个机器周期安排几个节拍?

    3)安排微操作时序。

    ① 微操作的先后顺序不得随意更改。

    ② 被控对象不同的微操作尽量安排在一个节拍内完成。

    ​ 单总线数据通路下,需要考虑总线冲突问题:一个节拍只能安排一次(片内)总线 Bus 传输。OP(IR) → CU/ID 不走 Bus。

    ​ 例题:王道 P243 应用题 05、唐朔飞第三版 P398 例题 10.1、10.2(10.3 有点变态)。

    ​ 注意非暂存寄存器到 ALU 的输入端也是要通过 Bus 的,不要冲突。

    ③ 占用时间较短的微操作尽量安排在一个节拍内完成,并允许有先后顺序。

    4)综合前几步列出微操作时间表。

  2. 进行微操作信号综合

    根据微操作时间表可写出各微操作控制信号的逻辑表达式。

    微操作命令的初始逻辑表达式,经化简、整理可获得能用现有门电路实现的微操作命令逻辑表达式。

    表达式一般包含的因素:机器周期、节拍、脉冲、操作码、机器状态条件。

  3. 画出微操作命令的逻辑图(根据逻辑表达式),并用逻辑门电路实现。

设计实例

CPU 控制方式

同步控制方式,一个机器周期安排 3 个节拍。

指令各阶段的微操作序列及时序安排

  1. 取指周期(所有指令都一样)

    ① T0 (PC) → MAR

    ② T0 1 → R 存储器空闲即可

    ③ T1 M(MAR) → MDR 在①之后

    ④ T1 (PC) + 1 → PC 在①之后

    ⑤ T2 (MDR) → IR 在③之后

    ⑥ T2 OP(IR) → CU/ID 在⑤之后

    从主存取数据,需独占一个节拍,在该节拍内不能有其他微操作与其存在先后执行顺序。

    ⑤、⑥占时较短,可安排在一个节拍。

    ⑤、⑥属于指令译码,在单独写取指周期微操作命令时可省,但在写指令周期时要体现。

    注意这里的 ⑤ (MDR) → IR 与间址周期的 ④ (MDR) → Ad(IR) 的区别。

  2. 间址周期(以一次间接寻址为例)

    ① T0 Ad(IR) → MAR

    ② T0 1 → R

    ③ T1 M(MAR) → MDR

    ④ T2 (MDR) → Ad(IR)

  3. 执行周期(视不同指令而定)

统一用 3 个节拍。T0、T1 基本上是用来取数/存数,用不了就空着,什么也不做。

算术右移中 AC$_0$ → AC$_0$ 表示 ACC 的符号位不变。

  1. 中断周期(只考虑保存 PC 值到内核栈中,栈指针寄存器为 ESP)

    ① T0 (ESP) - 4 → ESP 入栈先改栈顶指针

    ② T0 (ESP) → MAR

    ③ T0 1 → W 存储器空闲即可

    ④ T0 0 → EINT 硬件关中断

    ⑤ T1 (PC) → MDR PC 值压栈

    ⑥ T2 (MDR) → M(MAR)

    ⑦ T2 中断向量地址 → PC

微操作时间表

若某指令有表中所列出的微操作命令,其对应的单元格内为 1。

I 为间址标志。在取指周期的 T2 时刻,若 I = 1 则 IND 触发器置 “1”,标志进入间址周期,否则 EX 触发器置 “1”,标志进入执行周期。

在间址周期的 T2 时刻,若 IND = 0 则 EX 触发器置 “1”,进入执行周期,否则继续间接寻址。

在执行周期的 T2 时刻的最后,CPU 要向所有中断源发中断查询信号,若检测到有中断请求并满足响应条件,则 INT 触发器置 “1”,标志进入中断周期。

省略中断周期和部分指令的执行周期。

M(MAR) → MDR 的逻辑表达式

FE · T1 + IND · T1(ADD + STA + LDA + JMP + BAN) + EX · T1(ADD + LDA)
= T1{FE + IND(ADD + STA + LDA + JMP + BAN) + EX(ADD + LDA)}

产生 M(MAR) → MDR 的逻辑图

微程序控制器

微程序控制器采用控制逻辑实现,也就是将微操作信号代码化,使每条机器指令转化成为一段微程序并存入一个专门的存储器(控制存储器)中,微操作控制信号由微指令产生。

微程序控制的基本概念

设计思想

将每条机器指令编写成一个微程序,每个微程序包含若干微指令,每条微指令对应一个或几个微操作命令。这些微程序可以存到一个控制器存储器中。

执行一条指令的过程就是执行一个微程序的过程,用寻址用户程序机器指令的办法来寻址每个微程序中的微指令。

目前大多数计算机都采用微程序设计技术。

控制存储器 CM

用于存放微程序,在 CPU 内部,用 ROM 实现。

微地址

存放微指令的控制存储器的单元地址。

微程序

一条机器指令的功能由一段微程序来实现,每一种机器指令对应一个微程序。

微程序实际上是机器指令的实时解释器,是由计算机设计者实现编制好并存放在控制存储器中,一般不提供给用户。

微程序的结构与功能对程序员透明。

微指令

对机器指令执行步骤的描述。

微程序是微指令的有序集合。

一条微指令通常至少包括两大部分信息:

  1. 操作控制字段/微操作码字段:用于产生某一步操作所需的各种操作控制信号。
  2. 顺序控制字段/微地址码字段:用于控制产生下一条要执行的微指令地址。

微周期 / 微指令周期

从控制存储器中读取一条微指令并执行相应的微操作所需的时间。

通常为个时钟周期。

微命令

在微程序控制的计算机中,将控制部件向执行部件发出的各种控制命令(控制信号)称为微命令。

构成控制序列的最小单位。

例如,打开或关闭某个控制门的电位信号、某个寄存器的打入脉冲等。

微指令是若干微命令的集合。

微命令有相容性和互斥性之分:

  • 相容性微命令(可以并行完成)
  • 互斥性微命令(不允许并行完成)

微操作

执行部件收到微命令后所进行的操作称为微操作。

计算机中最基本的、不可再分解的操作。

微操作和微命令一一对应:微命令是微操作的控制信号,微操作是微命令的执行过程。

在组合逻辑控制器中也存在微命令和微操作这两个概念,它们并非只是微程序控制器的专有概念。

微程序控制器的基本组成

控制存储器 CM:简称控存,微程序控制器的核心部件,用于存放全部微程序,用 ROM 实现。

微地址形成部件:根据机器指令操作码产生对应微程序的首地址。

顺序逻辑:控制形成下一条微指令(即后续微指令)的地址,其输入与微地址形成部件、微指令的下地址字段以及外来的标志有关。

微指令地址寄存器 CMAR/μPC:控存地址寄存器,用于存放欲读出的微指令地址。

微指令寄存器 CMDR/μIR:控存数据寄存器,用于存放从控存读出的微指令。

微指令的编码方式/控制方式

指如何对微指令的控制字段进行编码,以形成控制信号。

目标:在保证速度的情况下,尽量缩短指令字长。

直接编码(直接控制方式)

无须译码,操作控制字段的每一位代表一个微操作命令,为 “1” 时有效。

优点:简单、直观,执行速度快,操作并行性好。

缺点:微指令字长过长,造成控存容量极大。

字段直接编码方式

将微指令的控制字段分成若干小字段,每个小字段独立编码,每种编码代表一个微命令,且各小字段编码含义单独定义,与其他小字段无关。

微命令字段分段原则:

  1. 把互斥性微命令组合在同一小字段,相容性微命令组合在不同小字段。
  2. 每各小字段的信息位不能太多,否则将增加译码线路的复杂性和译码时间。
  3. 一般每个小字段还要留出一个状态,表示本字段不发出任何命令(通常用全 0)。因此当某字段的长度为 3 位时,最多只能表示 7 个互斥的微命令。

优点:可以缩短微指令字长。

缺点:比直接编码方式慢(因为要通过译码电路后再发出微命令)。

字段间接编码方式 / 隐式编码

一个字段的某些微命令需由另一个字段中的某些微命令来解释。

由于不是靠字段直接译码发出的微命令,因此称为字段间接编码,也称隐式编码。

优点:可进一步缩短微指令字长。

缺点:削弱了微指令的并行控制能力,因此通常作为字段直接编码方式的一种辅助手段。

混合编码

把直接编码和字段编码(直接或间接)混合使用,以便能综合考虑微指令的字长、灵活性和执行微程序的速度等方面的要求。

微指令的地址形成方式

断定方式

由微指令的后继地址字段(也称下地址字段)指出后继微指令地址。

根据机器指令的操作码形成

机器指令取至 IR 后,微指令的地址由操作码经微地址形成部件形成,该部件输出的是对应机器指令(执行周期)微程序的首地址

可使用 PROM 实现,以指令的操作码作为 PROM 的地址,而相应的存储单元内容就是对应该指令微程序的首地址。

只读存储器可视为组合逻辑:任意时刻的输出都反映了输入地址指向的内容,且不需要读控制信号。

增量计数器法

(CMAR) + 1 → CMAR。

适用于后继微指令地址连续的情况。

分支转移

当遇到条件转移指令时,微指令出现了分支,必须根据各种标志决定下一条微指令的地址。

转移微指令格式如下:

转移方式指明判别条件,转移地址指明转移成功后的去向,若不成功则顺序执行。

也有的转移微指令设两个转移地址,条件满足时选择其中一个转移地址,条件不满足时选择另一个转移地址。

通过测试网络形成

图中微指令的地址分两部分:

  • 高段 h 为非测试地址,由微指令的 H 段地址码直接形成;
  • 低段 l 为测试地址,由微指令的 L 段地址码通过测试网络形成。

由硬件产生微程序入口地址

公共微程序段的第一条微指令的地址可由专门的硬件电路产生:

  • 当电源加电后,第一条微指令的地址可由专门的硬件电路产生,也可由外部直接向 CMAR 输入微指令的地址,这个地址即为取指周期微程序的入口地址。
  • 当有中断请求时,若条件满足, CPU 响应进入中断周期,此时需中断现行程序,转至对应中断周期的微程序。由于设计控制单元时已安排好中断周期微程序的入口地址,故响应中断时,可由硬件产生中断周期微程序的入口地址。
  • 同理,当出现间接寻址时,也可由硬件产生间址周期微程序的入口地址。

🙆️‍♀综合上述各种方法,可得出形成后续微指令地址的原理图:

图中多路选择器可选择以下 4 路地址:

  1. 指令寄存器(通过微地址形成部件)
  2. 微指令的下地址字段
  3. (CMAR) + 1 → CMAR
  4. 微程序入口地址(硬件产生)

微指令的格式

微指令格式与微指令编码方式有关,通常分水平型微指令和垂直型微指令两种 。

水平型微指令

一条微指令能定义并执行多个并行操作的微命令。

优点:微程序短,执行速度快。

缺点:微指令长(矮胖),编写微程序较麻烦。

从编码方式看,直接编码、字段直接编码、字段间接编码以及混合编码都属于水平型微指令。

垂直型微指令

采用类似机器指令操作码的方式,在微指令中设置微操作码字段,由微操作码规定微指令的功能。

一条垂直型微指令通常只能定义并执行一种微命令/基本操作(王道)。

通常一条微指令有 12 个微命令,控制 12 种操作(唐朔飞)。

优点:微指令短、简单、规整,便于编写微程序。

缺点:微程序长,执行速度慢,效率低。


👊水平型微指令 vs 垂直型微指令

  1. 水平型微指令并行操作能力强、效率高、灵活性强;垂直型微指令则较差。
  2. 水平型微指令执行一条机器指令所需的微指令数目少,因此速度比垂直型微指令的速度快。
  3. 水平型微指令用较短的微程序结构换取较长的微指令结构,垂直型微指令正相反,它以较长的微程序结构换取较短的微指令结构。
  4. 水平型微指令与机器指令差别较大,垂直型微指令与机器指令相似。

📝微指令格式的设计

  1. 水平型 or 垂直型?

    目前做过为数不多的题目都是考水平型,所以这里按水平型讨论。

  2. 编码方式?

    根据编码方式确定控制字段的位数。

    直接编码方式:微命令或者说微操作控制信号有多少个,控制字段就有多少位。

    字段直接编码方式:别忘了每个字段都要留出一个状态,表示本字段不发出任何微命令

  3. 条件测试/判别测试字段

    像分支转移指令还会有测试字段。

    对于互斥的外部条件,则可将测试字段类比于字段直接编码中的小字段,采用二进制编码,编码前别忘了也要 +1,即要包含一种条件都不生效的情况

  4. 地址形成方式?

    根据地址形成方式确定后继地址字段。

    一般都是断定方式,则控存存储单元数或微指令数与后继地址字段长度相关联。

微程序控制器的工作过程

微程序控制器的工作过程实际上就是在微程序控制器的控制下计算机执行机器指令的过程。

一条机器指令的执行过程(基于微程序控制器)

  1. 执行取微指令公共操作。

    在机器开始运行时,自动将取指微程序入口地址送入 CMAR,并从 CM 中读出相应的微指令送入 CMDR。

    取指微程序的入口地址一般为 CM 的 0 号单元。

    当取指微程序执行完后,从主存中取出的机器指令就已存入 IR 中。

  2. 由机器指令的操作码字段通过微地址形成部件产生该机器指令所对应的微程序的入口地址,并送入 CMAR。

  3. 从 CM 中逐条(不一定是顺序)取出对应的微指令并执行。

  4. 执行完对应一条机器指令的一个微程序后,又回到取指微程序的入口地址,继续第 1 步,以完成取下一条机器指令的公共操作。

以上是一条机器指令的执行过程(不包含间址周期和中断周期),如此周而复始,直到整个程序执行完毕。

所有指令的取指周期、间址周期、中断周期所对应的微指令序列都一样,可以共享使用。

顺序逻辑根据指令地址码的寻址特征位判断是否要跳过间址周期,根据中断信号判断是否进入中断周期。

一个微命令对应一根输出线。

控存中的微程序个数

控存中的微程序个数应为机器指令数再加上对应取指、间址和中断周期等公共的微程序数。

如果某指令系统有 $n$ 条机器指令,则 CM 中微程序(段)的个数至少是 $n + 1$ 个,即:

$n$ 个 执行周期微程序(段)+ 1 个取指周期微程序(段)。

物联网设备的 CPU 和一些早期的 CPU 不提供间接寻址和中断功能,因此这类 CPU 可以不包含间址周期和中断周期的微程序段。

微程序控制单元的设计步骤

主要任务是编写各条机器指令所对应的微程序。步骤如下:

  1. 写出对应机器指令的微操作命令及节拍

    1)写出每个周期所需要的微操作(参照硬布线)。无论是组合逻辑设计还是微程序设计,CPU 结构相同的部分,两种控制单元的微操作命令和节拍安排都是极相似的。

    2)补充微程序控制器特有的微操作。

    ① 取指周期:

    Ad(CMDR) → CMAR:每条微指令结束之后都需要将其下地址字段送 CMAR(除了微程序最后一条微指令)。

    OP(IR) → 微地址形成部件 → CMAR:取指周期的最后一条微指令完成后,要根据指令操作码确定其执行周期微程序入口地址。

② 执行周期:

Ad(CMDR) → CMAR。

Ad(CMDR) → CMAR 和 OP(IR) → 微地址形成部件 → CMAR 都要单独一个节拍。

  1. 确定微指令格式(微指令的编码方式、后继微指令地址的形成方式和微指令字长等)

    根据微操作个数决定采用何种编码方式,以确定 微指令操作控制字段的位数

    根据 CM 中存储的微指令总数,确定 微指令顺序控制字段的位数

    最后按操作控制字段位数和顺序控制字段位数就可确定 微指令字长

  2. 编写微指令码点

    根据操作控制字段每一位代表的微操作命令,编写每一条微指令的码点(即编写操作控制字段)。

动态微程序设计和毫微程序设计

静态微程序设计

通常指令系统是固定的,对应每一条机器指令的微程序是计算机设计者实现编号的,因此一般微程序无须改变,这种微程序设计技术称为静态微程序设计,其 CM 采用 ROM。

前面讲述的内容基本上属于这一类。

动态微程序设计

人们可以通过改变微指令和微程序来改变机器的指令系统,这种微程序设计技术称为动态微程序设计。

需要可写 CM 的支持,可以采用可擦除可编程只读存储器 EPROM。

动态微程序设计由于可以根据需要改变微指令和微程序,因此可以在一台机器上实现不同类型的指令系统,有利于仿真。

这种设计对用户的要求很高,目前难以推广。

毫微程序设计

微程序可看作是解释机器指令的,毫微程序可看作是解释微程序的,而组成毫微程序的毫微指令则是用来解释微指令的。

毫微程序设计采用两级微程序的设计方法:

  • 第一级微程序为垂直型微指令,并行功能并不强,但有严格的顺序结构,由它确定后续微指令的地址,当需要时可调用第二级。
  • 第二级微程序为水平型微指令,具有很强的并行操作能力,但不包含后续微指令的地址。第二级微程序执行完毕后又返回到第一级微程序。

两级微程序分别放在两级 CM 内。毫微程序控制存储器的基本组成如下:

硬件不由微程序直接控制,而是通过存放在第二级 CM(毫微存储器)中的毫微程序来解释的,直接控制硬件的是毫微指令。

值得注意的是,垂直型微指令不是和水平型微指令一条一条地对应,而是由水平型微指令(称为毫微指令)组成的毫微程序去执行垂直型微指令的操作。毫微指令与微指令的关系就好比微指令与机器指令的关系一样。

二级控制存储器虽然能减少控制存储器的容量,但因有时一条微指令要访问两次控制存储器,影响了速度。

硬布线 vs 微程序

硬布线控制器的特点

优点:由于控制器的速度取决于电路延迟,所以速度快。

缺点:由于将控制部件视为专门产生固定时序控制信号的逻辑电路,所以把用最少元件和取得最高速度作为设计目标,一旦设计完成,就不可能通过其他额外修改添加新功能。

微程序控制器的特点

优点:同组合逻辑控制器相比,微程序控制器具有规整性、灵活性、可维护性等一系列优点。

缺点:由于微程序采用了存储程序的原理,每条微指令都要从控制存储器中取一次,影响速度。

另外,微程序控制器的时序系统比较简单。硬布线控制器需要结合各微操作的节拍安排,综合分析,写出逻辑表达式,再设计成逻辑电路图,因此时序系统比较复杂;而微程序只需按照节拍的安排,顺序执行微指令,因此比较简单。

异常和中断机制

现代计算机中都配有完善的异常和中断处理系统,CPU 的数据通路中有相应的异常检测和响应逻辑,外设接口中有相应的中断请求和控制逻辑,操作系统中有相应的中断服务程序。这些中断硬件电路和中断服务程序有机结合,共同完成异常和中断的处理过程。

详见 OS1 中断与异常 和 OS5 I/O 控制方式-中断驱动方式

指令流水线

可从两方面提高处理器的并行性:

  • 时间并行:流水线技术

    将一个任务分解为几个不同的子阶段,每个阶段在不同的功能部件上并行执行,以便在同一时刻能够同时执行多个任务,进而提升系统性能,这种方法被称为流水线技术。

    采用流水线技术只需增加少量硬件就能把计算机的运算提高好几倍,因此成为计算机中普遍使用的一种并行处理技术,通过在同一个时间段使用各功能部件,使得利用率明显提高。

    RISC 都采用流水线技术,大部分 CISC 也采用了流水线技术。

  • 空间并行:多发射技术

    在一个处理机内设置多个执行相同任务的功能部件,并让这些功能部件并行工作。

指令流水线的基本概念

指令流水线

一条指令的执行过程可分解为若干阶段,每个阶段由相应的功能部件完成。如果将各阶段视为相应的流水段,则指令的执行过程就构成了一条指令流水线。

流水线设计原则

  • 指令流水段个数以最复杂指令所用的功能段个数为准。

  • 单个流水段的长度以最复杂的操作所花的时间为准。

指令阶段的划分

假定一条指令的执行过程分为以下 5 个阶段/功能段/流水段

  1. 取指 IF:从指令存储器或 Cache 中取指令。
  2. 译码/读寄存器 ID:操作控制器对指令进行译码,同时从寄存器堆中取操作数。
  3. 执行/计算地址 EX:执行运算操作或计算地址。
  4. 访存 MEM:对数据存储器或 Cache 进行读写操作。
  5. 写回 WB:将指令执行结果写回寄存器堆。

如何划分指令的执行过程,不同的教材有不同的划分方式。这里参考了历年 408 统考真题中的划分。

流水段的长度

假设主要功能单元的操作时间如下:

单周期处理器中,需要延伸时钟周期至 800ps 以满足最慢的指令 LDUR。

而在流水线中,每个流水段都需要一个时钟周期。因此按照流水线设计原则,每个流水段长度(即时钟周期)为 200ps。

虽然各子功能所用时间可能不同,但经过每个流水段的时间要都一样。

流水线方式并不能缩短单条指令的执行时间(这里反而比单周期串行执行时增加了 200ps),但对整个程序来说,执行效率得到了大幅提高。假设某程序有 N 条指令,单周期处理器所用的时间为 N×800ps,而流水线处理机所用的时间为 (N+4)×200ps。

考试中若无明确说明,则可不用考虑流水寄存器的时延。

指令流水线的执行方式

把 $k + 1$ 条指令的取指阶段提前到第 $k$ 条指令的译码阶段,从而将第 $k + 1$ 条指令的译码阶段与第 $k$ 条指令的执行阶段同时进行。

理想情况下,每个时钟周期都有一条指令进入流水线,每个时钟周期都有一条指令完成,每条指令的时钟周期数(即 CPI)都为 1。

优点:各部件的利用率明显提高。

缺点:硬件开销较大,控制过程也更复杂。

有利于实现指令流水线的指令集的特征

  1. 指令长度尽量一致

    有利于简化取指和指令译码操作,否则取指耗时不一,使取指部件机器复杂,也不利于指令译码。

  2. 指令格式尽量规整

    尽量保证源寄存器的位置相同,有利于在指令未知时(指令译码前)就可取寄存器操作数。

  3. 采用 Load/Store 型指令,其他指令都不能访问存储器

    这样可把 Load/Store 指令的地址计算和运算指令的执行步骤规整在同一个周期中,有利于减少操作步骤。

  4. 数据和指令在存储器中 “对齐” 存放

    有利于减少访存次数,使所需数据在一个流水段内就能从存储器中得到。

流水线的表示方法

  1. 指令执行过程图

    主要用于分析指令执行过程以及影响流水线的因素。

  2. 时空图

    主要用于分析流水线的性能。

空间:不同阶段所对应的不同的硬件资源。

装入时间:第一个任务进入流水线到输出流水线的时间。

排空时间:最后一个任务进入流水线到输出流水线的时间。

只有大量连续任务不断输入流水线,才能充分发挥流水线的性能。

流水线的分类*

按流水线使用级别的不同:

  1. 部件功能级流水线

    将复杂的算术逻辑运算组成流水线工作方式。

  2. 处理机级流水线

    把一条指令解释过程分成多个子过程。

  3. 处理机间级流水线

    一种宏流水,其中每一个处理机完成某一专门任务,各个处理机所得到的结果需存放在与下一个处理机所共享的存储器中。

按可以完成的功能:

  1. 单功能流水线

    只能实现一种固定的专门功能的流水线。

  2. 多功能流水线

    通过各段间的不同连接方式可以同时或不同时地实现多种功能的流水线。

按同一时间各段之间的连接方式:

  1. 静态流水线

    上下段连接方式固定。

    在同一时间内,流水线的各段只能按同一种功能的连接方式工作。

  2. 动态流水线

    上下段连接方式不固定。

    在同一时间内,当某些段正在实现某种运算时,另一些段却正在进行另一种运算。

    这样对提高流水线的效率很有好处,但会使流水线控制变得很复杂。

按流水线的各功能段间是否有反馈信号:

  1. 线性流水线

    从输入到输出,每个功能段只允许经过一次,不存在反馈回路。

  2. 非线性流水线

    存在反馈回路,从输入到输出过程中,某些功能段将数次通过流水线。

    这种流水线适合进行线性递归的运算。

流水线的基本实现

以一个简单的指令系统 MIPS 为例进行介绍。

MIPS 指令系统

采用 32 位定长指令字,字节编址,每条指令占 4 个单元。

指令格式仅三种:R 型(寄存器-寄存器操作)、I 型(16 位立即数操作)、J 型(无条件转移)。

  • R 型指令 31:26 操作码字段全 0,使用 5:0 funct 字段区分指令,汇编形式为 op(func) rd, rs, rt,功能为 R[rd] ← R[rs] op(func) R[rt]。
  • I 型带立即数的运算类指令,汇编形式如 addi rt, rs, imm16,涉及对 16 位立即数 imm16 进行符号扩展或零扩展,然后与 rs 的内容进行运算,最终把 ALU 的运算结果送目的寄存器 rt。显然,I 型运算类指令的功能与 R 型指令类似。
  • 访存指令 lw (读) 和 sw (写) 指令(属于 I 型),汇编形式为 lw rt, imm16(rs),功能为 R[rt] ↔ M[R[rs] + SignExt(imm16)]。
  • beq 条件分支指令(属于 I 型),汇编形式为 beq rs, rt, imm16,R[rs] 和 R[rt] 内容相等时跳转到 PC + 4 + 4 × imm16。

五段流水线数据通路实现概览(虚线表示控制信号)(貌似不包含 J 型指令):

所需部件

IF 段:PC、指令存储器(只读,可视为组合逻辑)、加法器(PC + 4)、多路选择器 MUX(控制写入 PC 的值是 PC + 4 还是分支目标地址)。

ID 段:控制器、寄存器堆、符号扩展单元、多路选择器 MUX(控制写入目的寄存器编号是 rt 还是 rd)。

EX 段:ALU、加法器(计算分支目标地址)、多路选择器 MUX(控制 ALU 的第二输入选自寄存器 rt 还是立即数符号扩展的值)。

MEM 段:数据存储器。

WB 段:多路选择器 MUX(控制将 ALU 运算结果还是数据存储器读出数据写回寄存器堆)。

流水段寄存器

流水线每一个功能段部件后面都要有一个流水段寄存器/流水寄存器/锁存器(除写回段外),根据其所连接的功能段来命名(IF/ID、ID/EX、EX/MEM、MEM/WB)。其作用是保存本段处理完成的数据和控制信号,以保证本段的执行结果能在下个时钟周期提供给下一流水段使用。

不同流水寄存器锁存的数据:

  • IF/ID 锁存器:从指令存储器取出的指令字、PC + 4。

  • ID/EX 锁存器:控制信号、从寄存器堆中取出的两个操作数 RS 和 RT、写寄存器编号 WriteReg#、立即数符号扩展的值、PC + 4。

  • EX/MEM:控制信号、ALU 运算结果、待写入数据存储器数据 WriteData、写寄存器编号 WriteReg#。

  • MEM/WB:控制信号、ALU 运算结果、数据存储器读出数据、写寄存器编号 WriteReg#。

综上,流水寄存器保存的信息包括:

  • 后面流水段需要用到的所有数据信息,包括 PC + 4、指令、立即数、目的寄存器、ALU 运算结果、标志信息等。
  • 前面传递过来的后面各流水段要用到的所有控制信号。

PC 可视为流水寄存器:给流水线的 IF 段提供数据。不过 PC 是可见体系结构状态的一部分,发生异常时其内容必须被保存下来,而流水寄存器的内容可被丢弃。

不同流水段寄存器存放的信息不同,因此流水段寄存器的位数不一定相同。

流水段寄存器对应用程序员透明,对系统程序员暂不明确(TODO)。

控制信号

主要的控制信号:

除了 BranchTaken 信号外,以上其余的 6 个控制信号均由控制器通过指令的操作码字段译码直接产生。

BranchTaken 信号的产生:由 ID 段控制器译码产生条件分支译码信号 Branch,经 ID/EX 流水寄存器传递至 EX 段,与 ALU 运算的标志 equal 信号进行逻辑与操作后,产生 BranchTaken 信号,接着反馈到 IF 段控制多路选择器进行分支处理。

AluOp 不止 1 位,取决于 ALU 有几种功能。其他控制信号都是 1 位。

执行过程

所有指令都需要完整经过流水线的各功能段,即使在某些功能段内没有实质性的操作。

本条指令 $I_1$ 进入 IF 段:

取指 IF

  • 将 PC 值作为地址从指令存储器中取出指令字。

  • 计算 PC + 4,并送入多路选择器的一个输入段。

  • 多路选择器根据之前指令 EX 段传来的 BranchTaken 信号和分支地址 BranchAddr,从 BranchAddr 和 PC + 4 中选择一个送入 PC 的输入端。

  • 下一个时钟到来时:

    1)将 PC + 4 和指令字锁存到 IF/ID 流水寄存器。

    2)更新 PC。

本条指令 $I_1$ 进入 ID 段,下条指令进入 $I_2$ 进入 IF 段。

译码/读寄存器 ID

  • 控制器根据 IF/ID 流水寄存器中的指令字(OP 和 funct 字段)生成 7 种控制信号。

  • 对于访存指令,需要取出寄存器 RS 的内容(基址),另外存数指令还需取出寄存器 RT 的内容(待写入数据 WriteData);对于 R 型指令,需要取出寄存器 RS 和 寄存器 RT 的内容(两个操作数)。

  • 多路选择器根据指令字和 RegDst 信号生成可能的写寄存器编号 WriteReg#(R 型指令是 rd,lw 指令是 rt)。

  • 符号扩展单元将指令字(I 型)中的 16 位立即数符号扩展为 32 位。

  • 下一个时钟到来时:将这些数据和 6 个控制信号(除 RegDst 信号)连同 PC + 4 锁存到 ID/EX 流水寄存器中。

本条指令 $I_1$ 进入 EX 段,下条指令 $I_2$ 进入 ID 段,下下条指令 $I_3$ 进入 IF 段。

执行/计算地址 EX

EX 段功能由具体指令指定。ALU 实际动作由控制器根据 OP 生成的 AluOp 控制信号(锁存在 ID/EX 流水寄存器)决定。

  • 对于访存指令,EX 主要用来计算访存地址:将 ID/EX 流水寄存器中锁存的 RS 内容与符号扩展后的立即数经过 ALU 相加得到访存地址。

  • 对于 R 型指令,EX 主要用来进行运算:将 ID/EX 流水寄存器中锁存的 RS 内容与 RT 内容经过 ALU 操作得到运算结果。

  • 对于条件分支指令(I 型),需要计算分支地址:将符号扩展后的立即数(偏移量)左移 2 位与 PC + 4(作为基址)经过加法器相加得到分支地址 BranchAddr。

    偏移量(I 型的立即数字段)基于指令字长,而指令存储器按字节编址,故需左移 2 位。

    ID/EX 流水寄存器中的 Branch 信号与 ALU 运算的标志 equal 信号相与生成分支转跳信号 BranchTaken。

    BranchAddr 和 BranchTaken 送 IF 段的多路选择器。

  • 下一个时钟到来时:将 ①ALU 运算结果、②ID/EX 流水寄存器中的写寄存器编号 WriteReg#、③ID/EX 流水寄存器中的 RT 内容(WriteData)、③后段需要的控制信号(MemWrite、MemToReg、RegWrite)锁存到 EX/MEM 流水寄存器。

本条指令 $I_1$ 进入 MEM 段,后续指令 $I_2$、$I_3$、$I_4$ 分别进入 EX、ID、IF 段。

访存 MEM

MEM 段功能也由具体指令指定。

  • 对于访存指令,主要是根据 EX/MEM 流水寄存器中锁存的 ALU 计算出的访存地址、WriteData 以及 MemWrite 信号对数据存储器进行读/写操作。

  • 下一个时钟到来时:

    1)WriteData 写入数据存储器(不一定)。

    2)将 ① EX/MEM 流水寄存器中锁存的 ALU 运算结果、② 数据存储器读出的数据(不一定)、③ EX/MEM 流水寄存器中的写寄存器编号 WriteReg#、④ 后段需要的控制信号(MemToReg、RegWrite)锁存到 MEM/WB 流水寄存器。

本条指令 $I_1$ 进入 WB 段,后续指令 $I_2$、$I_3$、$I_4$、$I_5$ 分别进入 MEM、EX、ID、IF 段。

写回 WB

WB 段功能也由具体指令指定。

  • 多路选择器根据 MEM/WB 流水寄存器中锁存的 MemToReg 信号,从同样来自 MEM/WB 流水寄存器锁存的 ALU 运算结果和数据存储器读出的数据这两者中选择一个作为写回数据 WriteBackData,连同 MEM/WB 流水寄存器中锁存的 WriteReg# 和 RegWrite 信号,送寄存器堆。
  • 下一个时钟到来时:将数据写回指定的寄存器(根据 RegWrite 信号决定是否真正写回)。

本条指令 $I_1$ 执行结束,后续指令 $I_2$、$I_3$、$I_4$、$I_5$、$I_6$ 分别进入 WB、MEM、EX、ID、IF 段。

流水线的冒险与处理

在指令流水线中,可能会遇到一些情况使得流水线无法正确执行后续指令而引起流水线阻塞或停顿,这种现象称为流水线冒险(hazard)。

根据导致冒险的原因可分为:结构冒险、数据冒险、控制冒险。

除了流水线冒险,Cache 缺失的处理过程也会引起流水线阻塞。

结构冒险

结构冒险(structural hazard),又称硬件资源冲突(hardware resource confict)。

产生原因

多条指令在同一时刻争用同一资源,即由硬件资源竞争造成。

解决办法

  1. 规定一个部件每条指令只能使用一次,且只能在特定阶段使用。

  2. 前一指令访存时,后一相关指令(及其后续指令)暂停一个时钟周期。

  3. 设置多个独立的部件 / 资源重复配置。

    对于访存冲突,可单独设置数据存储器和指令存储器,使取数和取指令操作各自在不同的存储器中进行。现代计算机都引入了 Cache 机制,而 L1 Cache 通常采用数据 Cache 和指令 Cache 分离的方式,因而也就避免了资源冲突的发生。

    对于寄存器访问冲突,可将寄存器的读口和写口独立开来。

数据冒险

数据冒险(data hazard),又称数据相关(data dependency)。

对流水线影响最严重的指令相关是数据相关。

产生原因

后面指令要用到前面指令的运算结果或从存储器取到的数据,但前面指令的结果还没产生或数据还没取到。

图示指令格式:
R 型:操作码 目的寄存器, 源操作数寄存器1, 源操作数寄存器2
D 型:操作码 目的寄存器/要写的数据, [基址寄存器, 偏移量]

时间轴上倒退的线会产生数据冒险。设存在访问寄存器操作的流水段是第 $m$、$n$ 段($m < n$),会发生数据冒险的范围是:某指令在 $n$ 段访问了寄存器 R,则该指令随后的 $n - m$ 条指令,若其第 $m$ 段也访问了寄存器 R,则会发生数据冒险(除去 RAR 相关)。上图的寄存器在时钟周期的前半部分写、后半部分读,在一个时钟周期内同时读写一个寄存器不会产生数据冒险,则随后的 $n - m - 1$ 条指令会发生数据冒险。

数据冒险分类

  1. 写后读 RAW (Read After Write) 相关🚩

    当前指令将数据写入寄存器后,下一条指令才能从该寄存器读取数据,否则就会读到错误数据(旧数据)。

  2. 读后写 WAR (Write After Read) 相关

    当前指令读出数据后,下一条指令才能写该寄存器,否则就会读到错误数据(新数据)。

  3. 写后写 WAW (Write After Write) 相关

    当前指令写入寄存器后,下一条指令才能写该寄存器,否则该寄存器的值不是正确的最新值。

指令按序发射按序完成时(或者说按序流动的流水线),只可能出现 RAW 相关(懂得都懂)。在非按序流动的流水线中,RAW 相关、WAR 相关、WAW 相关都有可能发生。

指令发射指的是指令从译码阶段进入执行阶段。

读后读 RAR (Read After Read) 相关,当两条连续的指令读取相同的寄存器时会产生。这种相关不会影响流水线。

统考只考察过 “按序发射按序完成” 方式。

解决办法

  1. 旁路(bypassing) / 转发(forwarding)技术

    设置相关转发通路,从内部缓冲中提前获取所需的数据,将数据通路中生成的中间数据直接转发到 ALU 的输入段,而非等到从程序员可见的寄存器或存储器中获取数据。

  2. 延迟执行相关指令

    把遇到数据冒险的指令及其后续指令都暂停一至几个时钟周期,直到数据冒险消失后再继续执行。

    load 指令装入的数据在随后一条指令就需要使用的情况称为 load-use 数据冒险,它无法用转发来解决(即使是转发,也不能产生时间轴上的倒退),只能通过延迟执行方式解决(除了编译优化方式)。

    但搭配转发技术可使 load-use 数据冒险只需延迟一个周期。

    通常把由于流水线阻塞而带来的延迟执行周期数称为延迟损失时间片

    延迟执行的方式可分为:

    1)软件插入 nop 指令

    最简单的是由编译器在数据相关的指令之间加若干 nop 指令(即空操作指令,除修改 PC 外其他什么操作都不做)。

    显然这种方式简化了硬件,但增加了时间开销(执行 nop 指令的时间)和空间开销(nop 指令所占的空间)。

    2)硬件阻塞(stall) / 气泡(bubble)

上图中,当 AND 指令处于 ID 级(CC 3)时,将 ID/EX 流水寄存器的 EX、MEM 和 WB 级控制信号都置为 0,可使得 AND 指令变成 nop 指令。

另外还需要保持 PC 和 IF/ID 流水寄存器内容不变:虽然 AND 指令变成了 nop 指令,但不意味着要重新取 AND 指令。

实际的效果是拉长了指令 AND 和 ORR 的时间:强迫 AND 指令和 ORR 指令在 CC 4 重复 CC 3 的操作,并延迟了 ORR 指令之后指令的取指。

硬件阻塞需要修改数据通路,控制相当复杂。

  1. 编译优化,通过调整指令顺序避免数据冒险。

  2. 通过硬件设计,使得寄存器文件在时钟周期的前半部分写、后半部分读,则在一个时钟周期内同时读写一个寄存器不会产生数据冒险。

控制冒险

由于指令执行顺序改变而引起的流水线阻塞称为控制冒险(control hazard)。

各种转移类指令(包括条件转移、无条件转移、调用、返回指令等)以及异常和中断等事件都会改变指令执行顺序,因而都可能会引发控制冒险。

由于分支指令(条件转移指令)而引起的控制冒险又称分支冒险(branch hazard)。

产生原因

当前要取哪条指令是由之前转移指令或其他改变 PC 值的指令的运行结果决定,但现在那条指令的结果还没产生,这就使得流水线断流,导致了控制冒险。

可以理解为对 PC 的写后读数据冒险:之前的流水线设计中,分支指令(包括无条件转移和有条件转移)对 PC 值的更新是在其 MEM 段完成的(要在 EX 段计算转移目标地址,另外条件转移指令还要在 EX 段通过计算设置条件码),这样后续指令要想正确取指必须要等到上一条条件分支指令的 MEM 段结束后才能进行。

解决办法

  1. 对转移指令进行分支预测

    尽早判别转移是否发生,尽早生成转移目标地址。

    1)简单(静态)预测

    总是预测条件不满足,即继续执行分支指令的后续指令。

    2)动态预测

    根据程序执行的历史情况,进行动态预测调整。

    当预测错误时(分支指令到达 MEM 级时才能决定),流水线控制必须确保预测错误的分支后面的指令执行不会产生实际效果,已经取出并译码的指令必须丢弃。指令丢弃指令意味着必须将流水线 IF、ID 和 EX 级中的三条指令都清除,并且必须从正确的分支地址处重新启动流水线。

    为了丢弃指令,只需要将最初的控制信号置为 0 即可,这一点与阻塞解决 load 指令的数据冒险类似。其不同之处在于当分支到达 MEM 级时必须分别改变其后处于 EX、ID 和 IF 级的三条指令的控制信号,而对于 load 指令的阻塞,只需要将其后处于 ID 级的一条指令(如前面数据冒险解决方案中描述的 AND 指令)的控制信号置为 0,并将其从流水线中退出即可。

  2. 预取转移成功和不成功两个控制流方向上的目标指令。

  3. 加快和提前形成条件码/减少分支延迟。

    将分支决策提前(到 ID 级)。越早开始条件分支的执行,则需要清空的指令就越少。

    需要提前两个动作到 ID 级:

    ① 计算分支目标地址:只需将计算分支地址的加法器从 EX 级移到 ID 级

    ② 判断分支条件:比较复杂,需要额外的旁路和冒险检测硬件,因为分支条件的判断可能依赖于还在流水线中的结果

    尽管有些困难,但将分支执行提前到 ID 级依然是一种有效的改进,因为它将分支发生时预测错误的代价减小到只有一条指令(原本是三条)。

  4. 延迟分支(delayed branch)

    调整指令的顺序,将一定会执行的指令放在分支指令后面(不受该分支影响的指令),这样流水线不停顿。但要注意不能改变这段代码原来的意义。

  5. 取出分支指令后立即阻塞流水线(NOP 或 bubble)

    对于分支冒险,可采用和前面解决数据冒险一样的硬件阻塞方式(插入气泡)或软件阻塞方式(插入空操作指令)。也即,假设延迟损失时间片为 C,则在数据通路中检测到分支指令时,就在分支指令后插入 C 个气泡,或在编译时在分支指令后填入 C 条 nop 指令。

    虽然流水线阻塞能用来解决各种冒险,但属于消极的方式,应尽量避免,因为它的效率低下:

    1)在较长的流水线中往往不能在第二级就解决分支问题(这意味着要在分支指令后添加多个周期的气泡)。

    2)条件分支指令是很常用的指令。


对现代流水线而言:

  • 结构冒险经常出现在浮点单元附近,因为浮点单元通常不能完全流水化。
  • 控制冒险更多地出现在整数程序中,因为整数程序中条件分支和预测的分支出现的频率更高。
  • 数据冒险在整数和浮点程序中都可能成为性能瓶颈。
  • 浮点程序中的数据冒险更容易处理,因为条件分支出现的频率更低,并且更多规则的存储器访问使得编译器能够尝试调度指令以避免冒险。
  • 整数程序中涉及大量的指针,规则的存储器访问更少,因此编译器优化就要困难一些。

流水线的性能指标

理想情况:指令各阶段花费时间相同;每个阶段结束后能立即进入下一阶段

目标:要在不过多增加硬件成本的情况下,尽可能地提高指令流水线的运行效率

吞吐率 TP

单位时间内流水线所完成的任务数量或输出结果的数量。

基本公式:TP = $\frac{n}{T_k}$($n$ 是任务数,$T_k$ 是处理完 $n$ 个任务所用时间)

$k$ 级流水线:

该流水线的实际吞吐率 TP = $\frac{n}{(n-1+k)\Delta t}$,当 $n \rightarrow \infin$ 时,得最大吞吐率 $TP_{max}$ = 1/Δt。

加速比 S

完成同样一批任务,不使用流水线所用的时间与使用流水线所用的时间之比。

基本公式:$S$ = $\frac{T_0}{T_k}$。$T_0$ 表示不使用流水线时(即顺序执行)所用的时间。

$k$ 级流水线的实际加速比 $S$ = $\frac{kn \Delta t}{(n-1+k) \Delta t}$ = $\frac{kn}{n-1+k}$,当 $n \rightarrow \infin$ 时,得最大加速比 $S_{max}$ = $k$。

效率 E

流水线的设备利用率。

时空图上,流水线的效率定义为:$E$ = $\frac{完成 n 个任务占用的时空区有效面积}{n 个任务所用的时间与 k 个流水段所围成的时空区总面积}$ = $\frac{kT_k-k(k-1)\Delta t}{kT_k}$。

当 $n \rightarrow \infin$ 时,最高效率为 1。

可以看出,流水线的效率包含了时间和空间两个因素。

高级流水线技术

高级流水线级数充分利用指令级并行 ILP (Instruction-Level Parallelism) 来提高流水线的性能。

两种增加指令级并行的策略:多发射流水线(multiple issue pipelining)技术、超流水线(super-pipelining)技术。

多发射流水线

通过同时启动多条指令(如整数运算、浮点运算、存储器访问等)独立运行来提高指令并行性。

要实现多发射流水线,其前提是数据通路中有多个执行部件,如定点、浮点、乘除、取数/存数部件等。通过采用多个执行部件,使流水线功能段能同时处理多条指令,处理器一次可以发射多条指令进入流水线执行。

实现多发射流水线需要完成的任务

  1. 指令打包

    指令打包任务就是将能够并行处理的多条指令同时发送到发射槽中。

    因此处理器必须知道每个周期能发射几条指令、哪些指令可以同时发射。这通过 推测(speculation) 技术来完成,可以由编译器或处理器通过猜测指令执行结果来调整指令执行顺序,使指令的执行能达到最大可能的并行。

    指令打包的决策依赖于 “推测” 的结果,主要根据指令间的相关性来进行推测,与前面指令不相关的指令可以提前执行,例如,如果可以推测出一条 load 指令和它之前的 store 指令引用的不是同一个存储地址,则可以将 load 指令提前到 store 指令之前执行;也可对分支指令进行推测以提前执行分支目标处的指令。

    不过,推测仅是 “猜测”,有可能推测结果是错误的,故需有推测错误检测和回退机制,在检测到推测错误时,能回退被错误执行的指令。因此,错误推测会导致额外开销。

    推测需要结合 软件推测硬件推测 来进行,软件推测指编译器通过推测来静态重排指令,此种推测一定要正确;而硬件推测指处理器在程序执行过程中通过推测来动态调度指令。

    根据推测任务主要由编译器静态完成还是由处理器动态执行,可将多发射技术分为两类:静态多发射动态多发射

  2. 冒险处理

    主要处理数据冒险和控制冒险(通过增加额外部件消除结构冒险)。在静态发射处理器中,部分甚至全部的数据冒险和控制冒险是由编译器静态处理的。相反,绝大多数的动态发射处理器通过硬件技术在执行时至少消除某些类别的冒险。

发射槽:在给定时钟周期内能够发射指令的位置,可以类比于短跑比赛中的起点位置。

静态多发射 / 超长指令字

静态多发射主要通过编译器静态推测来辅助完成 “指令打包” 和 “冒险处理”。

指令打包的结果可看成将同时发射的多条指令合并到一个长指令中。通常将一个时钟周期内发射的多个指令看成一条多个操作(具有多个操作码字段)的长指令,称为一个 “发射包”。所以,静态多发射指令最初被称为超长指令字 VLIW (Very Long Insturction Word),采用这种技术的处理器称为 VLIW 处理器。

在同一个周期内发射的指令类型是受限制的,例如,只能是一条 ALU/分支 指令 + 一条 Load/Store 指令。

以 2 发射流水线为例,

  • 优点:潜在性能将提高大约 2 倍(实际达不到)

  • 缺点:

    1)为消除结构冒险,需增加额外部件

    2)增加潜在的由数据冒险和控制冒险导致的性能损失

    例如,对于 Load-use 数据冒险,单发射流水线只有一条指令延迟,而 2 发射流水线有一个周期(2 条指令)延迟。

    对于 ALU-Load/Store 数据冒险,单发射流水线可以利用转发技术使 ALU 结果转发到 Load/Store 指令的 EXE 阶段;而 2 发射流水线,两条指令同时进行,ALU 的结果不能直接转发,因而不能提供给与其配对的 Load/Store 指令使用,只能延迟一个周期。

为了更有效地利用多发射处理器的并行性,必须有更强大的编译器能够充分消除指令间的依赖关系,使指令序列达到最大的并行性。

动态多发射 / 超标量流水线

动态多发射由处理器硬件动态进行流水线调度来完成 “指令打包” 和 “冒险处理”,能在一个时钟周期内执行一条以上指令。

采用动态多发射流水线技术的处理器称为 超标量(super-scalar)处理器。与 VLIW 处理器的不同点:

  • VLIW 处理器:编译结果与机器结构密切相关,结构有差异的机器上要重新编译。
  • 超标量处理器:编译器仅进行指令顺序调整,但不进行指令打包,由硬件根据机器的结构来决定一个周期发射哪几条指令。因此,编译后的代码能够被不同结构的机器正确执行。

为了更好地发挥超标量处理器的性能,多数超标量处理器都结合 动态流水线调度(dynamicpipelinescheduling) 技术,处理器通过指令相关性检测和动态分支预测等手段,投机性地不按指令顺序执行,当发生流水线阻塞时,根据指令的依赖关系,动态地到后面找一些没有依赖关系的指令提前执行。这种指令执行方式称为 乱序执行(out-of-orderexecution)

动态流水线的模型:

  • 一个指令预取和译码单元:有序发射
  • 多个并列执行的功能单元:乱序执行
  • 一个提交单元:有序提交

3 种动态流水线的执行模式(执行段的发射与完成):按序发射按序完成、 按序发射无序完成、无序发射无序完成。

无序发射无序完成的执行模式是针对执行段的,取指和译码段还是按顺序进行(即取指和译码段按序发射按序按序完成)。执行段发射前进行相关性检测,无关指令可先行发射和先行完成。

超流水线技术

通过增加流水线级数来使更多的指令同时在流水线中重叠执行。

超流水线并没有改变 CPI 的值,CPI 还是 1(一个小功能段总是占一个时钟周期),但其主频更高。因为理想情况下流水线的加速比与流水段的数目成正比,流水段越多,时钟周期越短,指令吞吐率越高,所以超流水先的性能比普通流水线好。

但流水段越多,指令执行不一定越快:

  1. 流水段缓冲之间的额外开销增大

    每个流水段有一些额外开销用于缓冲间传送数据、进行各种准备和发送等功能,这些开销加长了一条指令的整个执行时间。

    特别是当指令间逻辑上相互依赖时,开销更大。

  2. 流水段间控制逻辑变多、变复杂

    用于流水线优化和存储器(或寄存器)冲突处理的控制逻辑将随流水段数的增大而大增,这可能导致用于流水段之间控制的逻辑比段本身的控制逻辑更复杂。

不过流水线越多并行度越高是真的。

并行处理系统

并行处理系统的分类

并行处理系统面临各种技术问题的挑战,为此,人们提出了各种并行处理解决方案,针对这些解决方案,又有不同的并行处理技术分类,包括按指令和数据的处理方式划分、按地址空间访问方式划分、按存储访问时间是否一致划分、按处理单元的位置及其互连方式划分等不同的分类。

SISD、SIMD、MIMD

基于指令和数据的处理方式(指令流的数量和数据流的数量),将计算机体系结构分为 SISD、SIMD、MISD、MIMD 四类。

常规的单处理器属于 SISD,常规的多处理器属于 MIMD。

单指令流单数据流 SISD 结构

传统的串行计算机结构。

通常仅包含一个处理器和存储器,处理器在一段时间内仅执行一条指令。

为提高速度,有些 SISD 计算机采用流水线 CPU 和多体交叉编址存储器。

单指令流多数据流 SIMD 结构

指一个指令流同时对多个数据流进行处理,一般称为数据级并行技术。

通常由一个指令控制部件、多个处理单元和多个(局部)存储器组成。

各处理单元和各存储器之间通过系统内部的互连网络进行通信。在程序执行过程中,指令控制部件执行的还是一个串行的指令流,所有处于执行状态的处理单元同时执行相同的指令,所需的数据从连接在各个处理单元上专用的局部存储器中取得,因此,不同处理单元执行的同一条执行所处理的数据是不同的。

一个顺序应用程序被编译后,可能按 SISD 组织并运行于串行硬件上,也可能按 SIMD 组织并运行于并行硬件上。

对结构类似的大量数据进行相同处理,一条指令处理很多条数据:

  • 可用于优化 for 循环中对数组元素的重复处理。
  • 某些显卡在图像处理时,常采用 SIMD 对每个像素点进行完全一样的渲染(如加滤镜)。

在使用 case 或 switch 语句时效率最低,此时每个执行单元必须根据不同的数据执行不同的操作。

多指令流单数据流 MISD 结构

同时执行多条指令,处理同一个数据,实际上不存在。

多指令流多数据流 MIMD 结构

同时执行多条指令分别处理多个不同的数据,是目前大多数并行处理计算系统的处理方式。

SIMD 和 MIMD 是两种并行计算模式:SIMD 是一种数据级并行模式,而 MIMD 是一种并行程度更高的线程级并行或线程级以上并行计算模式。

多处理器系统和多计算机系统

采用 MIMD 计算模式的系统中一定包含多个计算机或多个处理器。为了区分不同的并行处理计算结构,有人提出从主存地址空间的访问方式上来区分多计算机系统和多处理器系统。

多处理器系统 / 共享存储系统

多处理器系统是共享存储多处理器 SMP (Shared Memory multiProcessor) 系统的简称。

具有共享的单一地址空间,每个处理器都可以通过存取指令来访问系统中的所有存储器,不管这些存储器是连接在一条总线上的共享存储器,还是连接在某个处理器上的本地存储器。

处理器通过存储器中的共享变量互相通信。多处理器在操作共享变量时需要进行同步,常用方法是通过对共享变量加锁来控制对共享变量的互斥访问。

每个处理器仍可在自己的虚拟地址空间中单独地运行程序。

多计算机系统 / 消息传递系统

多计算机系统指具有多个私有地址空间的并行处理系统,多计算机系统中每个计算节点都具有各自私有的存储器,并各自具有独立的主存地址空间,因此,这种并行处理系统采用的是一种分布式存储器访问方式。

显然,某一个计算节点无法通过存取指令来访问另一个节点的私有存储器,而要通过消息传递进行数据传送。

UMA 和 NUMA

对于多处理器系统,可以按照存储访问时间是否一致分为一致性内存访问(UMA)和非一致性内存访问(NUMA)两类。

统一存储访问 UMA 多处理器

每个处理器对所有存储单元的访问时间是大致相同的,即访问时间与哪个处理器提出访问哪个字无关。

如果所有处理器都共享一个存储器,那么,每个处理器通过 LOAD 指令和 STORE 指令访问任何一个存储单元,其访问时间是相同的。它是一种普遍使用的并行处理计算机结构。

非统一存储访问 NUMA 多处理器

某些访存请求要比其他的快,具体取决于哪个处理器提出了访存请求以及访问哪个字。

🍹这是由于主存被分割并分配给了同一机器上的不同处理器或内存控制器。若是本地存储器,访问时间就短;若是其他处理器所连接的存储器,则访问时间就长。

早期计算机,内存控制器没有整合进 CPU,访存操作需要经过北桥芯片(集成了内存控制器并与内存相连),CPU 通过前端总线 FSB 和北桥芯片相连,这就是统一存储访问(UMA)架构。随着 CPU 性能提升由提高主频转到增加 CPU 数量(多核、多 CPU),越来越多的 CPU 对前端总线的争用使得前端总线成为了瓶颈。为消除 UMA 架构的瓶颈,非统一存储访问(NUMA)构架诞生,内存控制器被集成到 CPU 内部。

NUMA 架构中,每个 CPU 都独立连接到一部分内存,CPU 直连的这部分内存被称为本地内存。CPU 之间通过 QPI 总线相连,CPU 可以通过 QPI 总线访问其他 CPU 的远程内存。如此,内存的访问出现了本地和远程的区别。显然访问本地内存要快于访问远程内存。

显然 NUMA 构架比 UMA 构架的运算扩展性要强:UMA 构架由于所有 CPU 共享相同的内存,增加 CPU 路数会加大访存冲突(通常 2 或 4 路性能最好),而 NUMA 理论上支持无限扩展。

处理器中不带高速缓存时,被称为 NC-NUMA;处理器中带有一致性高速缓存时,被称为 CC-NUMA。

Cache 一致性问题:由于每个 CPU 的 Cache 都是共享内存中的一部分副本,因此多处理器系统的 Cache 一致性既包括 Cache 和内存之间的一致性,还包括各 CPU 的 Cache 之间的一致性。也就是说,对内存同一位置的数据,不同 CPU 的 Cache 不应有不一致的内容。

多核处理器、对称多处理器、集群、网格

按处理单元的位置及其互连方式来分,MIMD 系统还可以分为多核(Multi-Core)、众核(ManyCore)、对称多处理器(SMP)、大规模并行处理机(MMP)集群、网格等。

多核处理器

指将多个处理单元集成到单个 CPU 中,每个处理单元称为一个核(core),通常也称片级多处理器。

每个核共享主存储器,同时既可以有自己的 Cache,也可以共享一个 Cache。

所有核通常是对称的。例如,2.4GHz 双核 CPU 中两个核的主频也是 2.4GHz。

一般采用偶数路 CPU,即通常多核 CPU 芯片的核数为2、4、8 等几种。

在多核计算机系统中,如要充分发挥硬件的性能,必须采用多线程(或多进程)执行,使得每个核在同一时刻都有线程在执行。

与单核上的多线程不同,多核上的多个线程是在物理上并行执行的,是真正意义上的并行执行,在同一时刻又多个线程在并行执行。

采用多核 CPU 可以降低计算机系统的功耗(相较于提高主频)和体积(相较于多个处理器),但通常比单核处理器的能耗更高(废话)。

对称多处理器 SMP

所谓对称多处理器 SMP (Symmetric MultiProcessor),是指将多个相同类型的 CPU 通过总线互连,并以等同地位共享系统所有资源,即多个 CPU 对称工作,无主次或从属关系。

因为各 CPU 共享相同的物理内存,每个 CPU 访问内存中的任何地址所需时间是相同的,因此,对称多处理器就是一种 UMA 结构多处理器。多核处理器系统、高档微机、工作站或服务器多用 SMP 结构。

对称多处理器 SMP 属于 UMA 结构的共享内存多处理器 SMP。

集群

集群(cluster)指通过高性能网卡将若干个普通 PC 或 SMP 服务器或工作站连接而成的并行处理系统。

集群中的每个计算节点(PC、SMP 或工作站)都有各自的内存储器和磁盘,主存地址空间都是计算节点各自私有的,因此,集群是一种典型的紧密耦合的同构多计算机系统。

显然,集群属于消息传递系统。

网格

网格(grid)是指用因特网等广域网络连接起来的远距离分布的一组异构计算机系统构成的分布式并行处理系统。

它是一种松散耦合的异构多计算机系统。云计算(cloudcomputing)服务器就是由网格发展而来的。

向量处理器与 SIMD

向量处理器是 SIMD 的变体,是一种实现了直接操作一维数组(向量)指令集的 CPU。

向量处理机是面向向量型数据的并行计算机,在向量各分量上执行的运算操作一般都是彼此无关、各自独立的,因而可以按多种方式并行执行,有流水线方式和阵列方式两种,大多以流水线结构为主。

主存储器容量的大小限定了机器的解题规模。向量处理机主要用于求解大型问题,必须具有大容量的主存,而且应该是集中式的公共存储器。

当高速运算流水线运行时,需要源源不断地供给操作数和取走运算结果,还要求主存具有很高的数据传输率,否则便不能维持高速运算,因此,多采用多个端口同时读取的交叉多模块存储器。

标量处理机中的数据相关(如 Load-use 冒险等)会影响流水线的执行,而向量处理机的流水线中,只可能在每个向量数据的开始处发生阻塞,而在随后的所有数据都不会发生流水线阻塞。即使标量处理机采用循环展开技术来降低阻塞次数,也比向量处理机中的阻塞现象要严重。

通常向量处理机都是进行浮点数运算(不是说整数运算不行)。

向量处理器在特定工作环境中极大地提升了性能,尤其是在数值模拟或相似的领域中。

硬件多线程

硬件多线程技术是一种共享单处理器中功能部件的技术。为每个线程提供单独的通用寄存器组、单独的程序计数器等,线程切换只需激活选中的寄存器,仅复制必要的线程资源,从而省略了与存储器数据交换的环节。

需要芯片组、操作系统、应用软件的支持。

采用硬件多线程的目的

减少线程切换中的开销,提供快速的线程切换。

共享 CPU 的高速缓存和功能部件,以单核模拟多核。

硬件多线程的实现方式

细粒度多线程、粗粒度多线程、同时多线程 SMT。

细粒度多线程

多个线程之间轮流交叉执行指令,多个线程之间的指令是不相关的,可以乱序并行执行。

在这种方式下,处理器能在每个时钟周期切换线程。

粗粒度多线程

连续几个时钟周期都执行同一线程的指令序列,仅在一个线程出现了较大开销的阻塞时(如 Cache 缺失),才切换线程。

在这种方式下,当发生流水线阻塞时,必须清除被阻塞的流水线,新线程的指令开始执行前需重载流水线。

开销比细粒度多线程大。

🐒上述两种多线程技术都实现了指令级并行,但线程级不并行。​

同时多线程 SMT

是上述两种多线程技术的变体。

在实现指令级并行的同时,实现线程级并行。也就是说,它在同一个时钟周期中,发射不同线程中的多条指令执行。

Intel 处理器中的超线程(Hyper-threading)就是同时多线程 SMT,即在一个单处理器或单个核中设置了两套线程状态部件,共享高速缓存和功能部件。

刷题笔记

  • “计算机字长 $n$ 位”、“$n$ 位 CPU”,严格来说都是指机器字长,但有时也可指数据字长(王道 P208 选择 06)。

  • 指令顺序执行时,PC 值总是自动加 1

    + “1”

  • 执行任何指令,单周期 CPU 的时间都要小于多周期 CPU

    执行任何指令,单周期 CPU 的时钟周期数都要小于多周期 CPU

    多周期 CPU 至少需要 2 个时钟周期才能执行一条指令,CPI > 1

    单周期 CPU 执行任何指令的时间不一定都会小于多周期 CPU,这取决于单周期 CPU 和多周期 CPU 的时钟周期的长短,以及该指令在多周期 CPU 下所需的时钟周期数。

  • 为了硬件设计方便,指令字长都和存储字长一样大

    为了硬件设计方便,指令字长一般取字节或存储字长的整数倍

  • (控存)存储单元数要求是 2 的 $n$ 次幂。

  • 垂直型微指令的特点是:采用微操作码。

  • 控制单元设计(微操作序列及时序安排)还是不熟啊,不能光看不练。

  • 常规标量单流水线处理机,即处理器的度为 1。

  • 计算流水线吞吐率和加速比还是用指令执行过程图更方便。

    计算效率要用时空图。

  • 避免结构冒险的基本做法是使每个指令在相同流水段中使用相同的部件。

  • 前面的分支指令和后面的 ALU 运算指令之间肯定不会发生数据冒险

    分支指令 slt r1, r2, r3,其功能是将源寄存器 R2 与源寄存器 R3 中的值进行比较,如果 R[r2] < R[r3],则将目标寄存器 R1 中的值设置为 1,否则设置为 0。

  • 在没有阻塞的情况下,PC 的值在每个时钟周期都会改变。

  • 经典五段流水线中:

    1)load 指令的 MEM 阶段在 use 指令的 EX 阶段的前一个时钟周期即可避免 load-use 数据冒险(从 MEM/EX 流水寄存器中获取 load 指令取出的数据,使用转发技术直接传送到 use 指令使用的 ALU 的一个输入端)。因此 load-use 数据冒险会引起至少一个时钟周期的阻塞(搭配转发技术可使 load-use 数据冒险只需延迟一个周期)。

    2)一般的寄存器 RAW 数据冒险在使用转发技术后不需要延迟:后面两条指令从 EX/MEM 流水寄存器中取即可,后面第三条指令在其 ID 段的时钟周期的后半部分直接读即可。

  • 判断发生流水线阻塞的指令,不能只看发生数据冒险的指令,还要考虑其他流水线冒险的情况。

    另外还要知道,会引起流水线阻塞的除了流水线冒险,Cache 缺失的处理过程也引起。

  • 无条件转移指令不会发生控制冒险

    转移指令的转移目标地址要在其 EX 阶段才能确定,在 MEM 阶段才更新到 PC 中,所以无条件转移指令执行到 MEM 阶段会导致其后的三条指令(IF、ID、EX 级)需要被清除。

    同理,有条件转移指令在条件达成时也会影响其后三条指令(有条件转移指令在 EX 阶段还要根据运算结果设置条件码)。

    所以在使用阻塞方式解决转移指令引起的冲突时,要保证下一条指令的 IF 段在转移指令的 MEM 段的下一个时钟周期,即中间要隔三条空指令。

  • 超标量通过内置多条流水线来同时执行多个处理器,实质是以空间换取时间。