第八章 CPU的结构和功能

重难点注意!

周期流水和中断
指令流水非常非常重要绝对会考,怎么构成指令流水,几个周期构成流水,以及产生影响的主要因素,如何解决。要会计算流水效率。
中断请求标记 电路图不需要记住
中断隐指令概念要记住
屏蔽字一定会考,且占比高

我们已经学习完了CPU的指令系统,但是指令是如何被CPU调用的呢?这就涉及到中断系统和CU部分了。本章从分析CPU的功能和内部结构入手,详细讨论计机器执行一条指令的全过程,以及为了提高数据处理能力、开发系统的并行性所采取的指令流水技术。

CPU的结构

在第一章我们知道CPU主要由运算器和控制器组成。运算器已经在第六章学习完毕,这里主要讨论CPU的控制器的功能。

运算器的功能:

  • 实现算术运算和逻辑运算(数据加工)

控制器的功能:

  • 取指令(指令控制)
  • 分析指令(指令控制)
  • 执行指令,发出各种操作命令(指令控制)
  • 控制程序输入及结果的输出(操作控制)
  • 总线管理(时间控制)
  • 处理异常情况和特殊请求(处理中断)

CPU必须具有指令控制、操作控制、时间控制、处理终端和数据加工的能力。

image-20240619175634266

其中指令控制与PC、IR有关;操作控制和时间控制则涉及到CU和时序电路;数据加工与ALU和寄存器有关;处理终端则和中断系统有关。

寄存器

CPU的寄存器分为用户可见寄存器和用户不可见寄存器。用户不可见寄存器很多,例如流水段之间的流水段寄存器。

用户可见的寄存器有:

  • 通用寄存器,存放操作数
  • 数据寄存器,存放操作数
  • 地址寄存器,存放地址
  • 条件码寄存器,存放条件码

不可见的寄存器有:

  • 控制寄存器

    以取指令为例子:PC➡️MAR➡️M➡️MDR➡️IR

    其中MAR、MDR、IR对用户不可见,而PC可见

  • 状态寄存器

    反映指令执行结果的情况或者计算机软件硬件的状态。比如状态寄存器,PSW寄存器(比如8086的flag寄存器)。

控制单元CU和中断系统

其中,CU负责产生全部指令的微操作命令序列,包括:

  • 组合逻辑设计,即硬连线逻辑
  • 微程序设计,即存储逻辑

以上内容将在第十章介绍。

中断系统,将在本章节后续小节具体介绍。

ALU

参见第六章

指令周期

指令周期,指的就是CPU取出并执行一条指令所需要的全部时间。

一般来说,完成一条指令,可以分为两个阶段:

  • 取指、分析;称取指周期
  • 执行;称执行周期

不过,具体来说,每条指令的指令周期一般不同,比如Nop就只有取指周期。指令周期一共可以细分为四个周期:取值周期、间址周期、执行周期、中断周期。

具体的流程可以参考下图:

image-20240619193003466

控制器在指令执行的不同阶段要发出不同命令。尽管都是内存读写操作,不同周期功能不同,读写位置不同:

  • 取指周期,取出指令,送入IR;
  • 间址周期,取出地址,送入IR或MDR的地址码部分;
  • 执行周期,读出来的数据放入CPU寄存器中;
  • 中断周期,程序断点存入内存。

CPU必须标注出当前处于指令的哪个阶段,以便于控制器发出相应的控制操作,这些标志就是CPU 工作周期的标志。为了区分它们,在CPU内可以设置四个标志触发器:

FE、IND、EX、INT分别对应取指、间址、执行和中断四个周期,并以“1”状态表示有效。

指令流水

指令流水是一项极其重要的技术,需要重点掌握。无论是嵌入式,还是服务器,都使用流水技术。

我们先前提到过,要提高机器速度,可以从几个方面入手:

  1. 提高访问速度:比如使用高速芯片、Cache、多提并行
  2. 提高I/O和主机之间的传送速度:比如使用中断、DMA、通道、I/O处理机等技术
  3. 提高运算器的速度:比如使用高速芯片,改进算法,使用快速进位链等

现在,我们介绍第四种方法——提高整机的处理能力,即改进系统结构,开发系统的并行性

所谓并行,包含并发性和同时性两个概念:

  • 并发,指两个或两个以上事件在同一时间段发生
  • 同时,指两个或两个以上事件在同一时刻发生

概括来说,只要时间上存在相互重叠,就具有并行性。

并行性的等级又分为作业级或程序级、任务级或进程级、指令之间级和指令内部级。前两者称为粗粒度,用软件实现;后两者称为细粒度,用硬件实现。

原理

我们先来看指令的串行执行:

可以看到,取指令时,只有取指令的部件在工作;执行指令时,只有执行指令的部件在工作。总会有一个部件空闲,没有充分的发挥出计算机的效率。

接着我们使用指令的二级流水:

image-20240619195335432

可以看到,如果取指和执行阶段的时间完全重叠,则指令周期减半,速度提高了一倍。但实际情况下,流水线很难满负荷运转,因为指令不会仅分成两个阶段,指令之间也有相关性,不同阶段的耗时也不同。

影响指令流水的因素如下:

  • 执行时间>取指时间
  • 条件转移指令对指令流水的影响:必须等上一条指令执行结束才能确定下一条指令的地址,这造成了很大的时间损失。

尽管这些因素影响了流水线的效率,但还是可以获得加速。

为了进一步提高处理速度,我们把处理过程分为更细的几个阶段:

  • FI:取指令
  • DI:指令译码
  • CO:形成操作数的地址
  • FO:取操作数
  • EI:执行
  • WO:结果写回

于是,我们就能根据这里六个阶段,设计一个六级流水:

image-20240619200109839

完成一条指令需要6个时间单位:

  • 如果串行执行,则需要6×9=54个时间单位
  • 如果六级流水,则需要14个时间单位

可以看出流水线大大地提高了计算机的运行效率。

影响流水的因素

要保持高效率,我们就必须要保持流水充分流动,不发生断流。但由于在流水线中会出现三个相关,所以很难实现不断流动。三个相关即:

  • 结构相关,不同指令争用同一硬件部件
  • 数据相关,后继指令需要用到前面指令的执行结果
  • 控制相关,遇到分支指令和其他改变PC值引起的相关
结构相关

要解决结构相关的问题,我们通常采用以下方法:

  • 停顿,让一个指令先执行
  • 指令存储器与数据存储器分开,避免取指令和取操作数产生冲突
  • 指令预取技术,适用于访存周期短的情况,利用空闲时间取出多条指令放入指令缓冲寄存器

image-20240619200736020

另外,除了存储器资源,其他资源也都会冲突,例如寄存器。

数据相关

数据相关指不同指令因重叠操作,可能改变操作数的 读/写 访问顺序。

数据相关又分为三种:写后读相关,读后写相关和写后写相关

  • 写后读相关·RAW

    image-20240619201634128

  • 读后写相关·WAR

    image-20240619201641779

  • 写后写相关·WAW

    image-20240619201647894

解决方法有二:后推法和旁路技术。

  • 后推法:等待第一条指令将结果写入寄存器后,第二条指令才开始读执行。这样做显然需要停顿流水线。
  • 旁路技术:相关专用通路、前向通道:不需要等到结果送回寄存器,运算器结果产生后,直接作为输入,开始第二条指令执行。

在按序流动的流水线中,只可能出现RAW相关;而在非按序流动的流水线中,则三种都可能出现。

控制相关

由转移指令引起,不得不停止等待判断的结果才知道接下来该执行哪里。

image-20240619202134351

假设指令3是转移指令,直到指令2结束才知道条件是否成立。指令4到指令7已经全部取出开始执行了,这些操作全部作废,在9到12时间单元没有结果输出,产生性能损失。

为了解决控制相关,我们一般使用猜测法尽早判断转移是否发生。这个方法很复杂,已经超出了教纲,可以自行查阅资料了解。

流水线性能

我们主要学习流水线性能的三个有关定义:吞吐量、加速比和效率。

吞吐率

吞吐率指单位时间内,流水线所完成指令或输出结果的数量。

mm段流水线的各段时间为Δt\Delta t

  • 最大吞吐率为流水线连续流动达到稳定状态下的状态,即没有资源冲突,没有数据相关冲突,没有条转等,每经过一个t就有一个结果输出,有:

    Tpmax=1ΔtT_{pmax}=\frac{1}{\Delta t}\\

  • 实际吞吐率:连续处理 n 条指令的吞吐率为:

    Tp=nmΔt+(n1)ΔtT_p=\frac{n}{m·\Delta t+(n-1)·\Delta t}\\

    第一条指令需要时间mt,如果流水线很理想,其后一条指令有(m-1)段都已经在执行完第一条指令后并发完成,故只需要额外t时间就可完成第二条指令。以此类推,除了第一条指令花费mt外,剩下的(n-1)条指令均只需要额外的一个t即可输出结果,总耗时为(n-1)·t

仅当n>>m时,Tp≈Tpmax

加速比

设加速比为SpS_p,定义加速比为 m 段的 流水线的速度 与等功能的 非流水线的速度 之比。

设流水线各段时间为Δt\Delta t

完成n条指令在m段流水线上一共需要:T=mΔt+(n1)ΔtT=m·\Delta t+(n-1)·\Delta t

完成n条指令在等效的非流水线上共需:T=nmΔtT^{'} =nm·\Delta t

Sp=nmΔtmΔt+(n1)Δt=nmm+n1S_p=\frac{nm·\Delta t}{m·\Delta t+(n-1)·\Delta t}=\frac{nm}{m+n-1}\\

效率

效率即流水线中各功能段的利用率,由于流水线有建立时间和排空时间因此各功能段的设备不可能一直处于工作状态。

image-20240619204921547

定义效率:

E=流水线各段处于工作状态的时间区流水线各段总的空时间区=mnΔtm(m+n1)Δt=nm+n1=Spm=TpΔtE=\frac{流水线各段处于工作状态的时间区}{流水线各段总的空时间区}=\frac{mn\Delta t}{m(m+n-1)\Delta t}\\=\frac{n}{m+n-1}=\frac{S_p}{m}=T_p\Delta t

其实就是实际吞吐率×各段用时

中断系统

前面介绍过,采取中断的方式可以使CPU和I/O系统并行工作,提高效率。其实在实际运用中,除了I/O设备中断外,还有其他的中断。常见的中断类型如下:

  • 人为设置的中断,比如转管指令
  • 程序性事故,比如溢出
  • 硬件故障
  • I/O设备
  • 外部事件,比如键盘中断

中断系统为了处理这些中断,需要处理以下几个问题:

  1. 各个中断源如何向CPU提出中断请求?

    中断请求标记

  2. 多个中断源提出请求时,系统如何确定优先响应哪个中断源?

    中断判优逻辑

  3. CPU在什么条件、什么时候、以什么方式响应中断?

    EINT、查询、中断向量表

  4. CPU响应中断后如何保护现场?

    中断隐指令

  5. CPU响应中断后,如何停止原程序执行而转入中断服务程序的入口地址?

    中断隐指令

  6. 中断处理结束后,CPU如何恢复现场,如何返回到原程序的中断处?

    中断服务程序

  7. 中断处理过程中出现了新的中断,如何处理?

    中断屏蔽技术

接下来我们的内容将主要聚焦在解决这七个问题上。

(如果你学过8086汇编语言,你会发现这里的大多数问题在汇编语言的中断章节里都有介绍,如果你没有接触过汇编或者忘记了,可以参考这篇文章:汇编味小饼干 | Adam8en の 8log

中断请求标记

中断系统通过设置中断请求标记触发器来判断是哪个中断源提出了中断要求,简称中断请求标记INTR。

image-20240619212012390

一个中断源对应一个INTR触发器,多个INTR组成中断请求标记寄存器。当触发器被设为1时,表明有对应中断请求。中断系统的触发器越多,代表计算机对中断的处理能力越完善。

INTR既可以集中在CPU的中断系统内,也可以分布在各个中断源的接口电路中。

中断判优逻辑

判优实现有两种:硬件实现和软件实现。

硬件实现(排队器)又分两种:一种分散在各个中断源的接口电路中,使用链式排队器进行优先级划分;一种集中在CPU内,按照优先顺序1、2、3、4排列。当最高级的INTR=1时,可以封住比它级别的的中断源的请求。

image-20240619212505410

软件实现即通过程序查询,从高到低逐级查询是否有中断请求,

image-20240619212605092

中断服务程序入口地址的查找

同样分为硬件向量法和软件查询法两种。

硬件向量法,即用向量地址形成部件,输入排队器输出,输出中断向量地址。速度快,但灵活性低。

硬件向量法又有两种方法:

  1. 中断向量地址包含一条跳转指令,跳转到入口地址
  2. 在内存某一地方保持了入口地址,要把它取出来,送入PC

第二种方法允许用户修改中断向量表的入口地址,即更新中断例程,灵活性相对较高。因为速度更快,计算机大多使用硬件向量法定位入口程序地址。

软件查询法即编写对应的程序,内容由程序员编制,可以灵活改变优先级,但是查询速度慢。目前计算机可以灵活使用两种方法找到入口地址。

中断响应

响应中断的条件

允许中断触发器EINT=1时。(类似8086汇编中的IF标志位,可以用sticli设置)

响应中断的时间

在指令执行周期结束时刻,由CPU 发查询信号

image-20240619213414922
中断隐指令

中断隐指令,主要指的是三个步骤:

  1. 保护程序断点

    断点存于内存的特定地址(0号地址)或者断点进栈

  2. 寻找服务程序入口地址

    硬件向量法或者软件查询法

  3. 硬件关中断

    • 单重中断:执行中断服务程序时不再允许发生中断
    • 多重中断:保护程序软硬件状态的过程中,不允许发生中断

为什么叫这三个操作为“隐指令”,是因为它们都由计算机的硬件自动完成,而不是在某一条具体指令的驱动下完成。

保护和恢复现场

保护现场,指的是保存当前执行程序的断点地址以及寄存器中的内容。前者由中断隐指令完成,而后者交由中断服务程序完成。一般来说,是把当前过程中寄存器的值入栈来实现对现场的保护。

恢复现场,即跳转回原程序的断点地址并恢复其寄存器的内容,全部由中断服务程序完成。

image-20240620170454344

即把寄存器内容POP出栈,然后调用IRET指令返回。

中断屏蔽技术

多重中断

前面我们说过,对于单重中断而言,如果进入中断程序,是不允许响应其他中断的。但如果在执行中断服务程序的过程中,出现了更重要的,需要及时处理的新事件,怎么办呢?这时候我们引入了多重中断屏蔽技术。

多重中断,即CPU在响应某个中断服务程序时,出现了新的中断请求,CPU又响应了这个请求。此时,CPU就会暂时停止这个服务程序,转去执行新的中断服务程序,执行完毕后再返回执行原来的中断服务程序。即“中断的中断”,又称为中断嵌套。

image-20240620171033609

要实现多重中断,需要满足以下条件:

  1. 提前设置开中断指令,否则CPU不会响应可屏蔽中断。
  2. 优先级别高的中断源有权中断优先级别低的中断源。
image-20240620171411538

如上图所示,中断源优先级为A>B>C>D。可以看到D在返回的过程中,接收到了中断源A的信号。此时CPU转而去执行中断A,然后再转回执行中断D,最后返回。

在中断B执行完后,C的中断请求还在,此时CPU只要发出中断查询信号就可以继续执行中断。

屏蔽技术

我们通过硬件屏蔽触发器来设计中断屏蔽字,来改变中断优先级,提高系统的灵活性。

将排队器集中在CPU内,加上屏蔽条件,就可以组成具有屏蔽功能的排队器,如图所示:

image-20240620172902781

每个中断请求触发器都对应有一个屏蔽触发器,将所有的屏蔽触发器组合在一起,就可以构成一个屏蔽寄存器,屏蔽寄存器的内容称为屏蔽字。屏蔽字的内容和中断源的级别一一对应。

image-20240620173142882

直观来看,就是说屏蔽字的数值越大,它的优先级越高

通过设置屏蔽字,我们就可以改变处理优先等级。注意区分处理优先等级和响应优先等级的概念。

  • 响应优先级:是CPU通过轮询中断触发器实现的,因为是通过硬件确定的,所以不可改变。
  • 处理优先级:可以通过更改屏蔽字来改变CPU对中断触发器的处理优先级。

也就是说,通过设置屏蔽字,CPU仍然会按照硬件设计的顺序优先响应排在前面的中断源,但是在这之后,中断服务程序可能会被优先级更高的屏蔽字打断,转而去处理其他中断服务程序。

比如有如下中断源:

image-20240620173902475

如果ABCD同时发出中断请求,就会有如下过程:

  1. 首先,CPU优先响应请求A,此时A的处理优先级也是最高,没有中断程序打断,所以CPU会先执行完A的中断服务程序。
  2. 接着,CPU优先响应请求B,但是B的处理优先级低于D和C,所以将被打断。
  3. C的响应优先级高于D,故CPU优先响应请求C,但是C的处理优先级低于D,故被D打断。
  4. 现在CPU开始处理请求D,没有被打断,于是处理完D的中断服务程序。
  5. CPU处理完D转回处理中断C。
  6. CPU处理C未遭打断,故成功执行完中断服务程序C。
  7. 最后,CPU转回处理并执行完中断服务程序B。

以上过程绘图如下:

image-20240620174630650

注意,所有中断只会被响应一次。在处理完一个中断请求后,不需要再次响应已经被响应过的中断,而是直接返回处理原先的中断。

在开启屏蔽字技术后,中断处理请求流程图增加了置屏蔽字和恢复屏蔽字部分,绘图如下:

image-20240620175626160

在恢复现场前关中断是为了防止恢复过程中被新的中断打断,在恢复现场和屏蔽字后,必须要重新打开中断。

……

……

第五部分到此结束!敬请阅读第六部分💸


11