1.CPU的基本功能和结构
1.1.CPU 的功能
1.1.1.CPU 的具体功能
CPU 具体功能包括:
- 指令控制:完成取指令、分析指令和执行指令的操作,也即程序的顺序控制。
- 操作控制:一条指令的功能是通过若干操作信号组合来实现的。CPU 管理并产生由内存取出的每条指令的操作信号,把各种操作信号送往相应部件,从而控制这些部件按指令的要求进行动作。
- 时间控制:对各种操作加以时间上的控制。时间控制要为每条指令按时间顺序提供应有的控制信号。
- 数据加工:对数据进行算数和逻辑运算。
- 中断处理:对计算机运行过程中出现的异常情况和特殊请求进行处理。
1.1.2.每个部件的功能
CPU 由运算器和控制器构成,其中运算器主要作用就是对数据进行加工;控制器主要作用就是协调和控制计算机各部件执行程序的指令序列,具体来说:
- 取指令:自动形成指令地址,自动发出取指令的命令。
- 分析指令:操作码译码(分析本条指令要完成什么操作);产生操作数的有效地址。
- 执行指令:由 “操作命令” 和“操作数地址”,形成操作信号控制序列,控制运算器、存储器以及 I/O 设备完成相应的操作。
- 中断处理:管理总线及输入输出;处理异常情况(比如掉电、浮点异常等)和特殊情况的请求(打印机请求打印一行字符等)。
1.2.运算器基本结构
1.2.1.运算器概述
运算器核心是 ALU 算数逻辑单元。
ALU需要两个操作数,经过处理后,就会输出运算结果。
运算器是计算机中加工数据的中心,除了 ALU 外,它还有很多寄存器,这里先给出它们的大致功能:
- 暂存寄存器:用于暂存从主存读过来的数据,该数据不能存放在通用寄存器中,否则会破坏其原有内容。暂存寄存器对应用程序员是透明的。
- 累加寄存器:它是一个通用寄存器,用于暂时存放 ALU 的运算结果,可以作为加法运算的一个输入端。
- 通用寄存器组:如
AX
、BX
、CX
、DX
、SP
等,用于存放操作数(包括源操作数,目的操作数及中间结果)和各种地址信息。注意SP
是堆栈指针,用于指示栈顶地址。 - 程序状态字寄存器:保留由算数逻辑运算指令或测试指令的结果而建立的各种状态信息,如溢出标志(
OF
)、符号标志(SF
)、零标志(ZF
),进行标志(CF
)等。PSW 中的这些位参与并决定微操作的形成。 - 移位器:对操作数或运算结果进行移位运算。
- 计数器:控制乘除运算的操作步数。
1.2.2.两种数据通路设计方式
接下来介绍两种数据通路设计方式,来详细探讨这些寄存器的作用。
注意下面的叙述仅仅是了解,不知道没有关系,后面会具体学习的。
数据通路:是指执行部件之间传送信息的路径,由控制信号控制。
1.2.2.1.专用数据通路
专用数据通路:根据指令执行过程中的数据和地址的流动方向安排连接线路。例如下图中每个寄存器与 ALU 都有专门的数据连线。
任何一个通用寄存器中保存的数据都有可能作为 ALU 的输入,因此需要提供两组连线分别将通用寄存器两端连接至 ALU 两端(注意连线并不是只有一根,而是要视具体的数据传输情况而定) 。
专用数据通路方式下,有可能多个寄存器会同时向 ALU 传输数据,这显然是不合理的,主要有以下两种解决方案:
多路选择器(MUX):根据控制信号选择一路输出,每个多路选择器都可以决定要把哪一个信号输出。比如下图左侧的多路选择器信号为 00,就表示让 $R_{0} \(通过,右侧的多路选择器信号为 01,就表示让\)R_{1} $通过 。
三态门:控制每一路是否可以输出。比如下图, $R_0out $为 1 时表示 $R_{0} $的数据可以输出到 A 端, $R_0out $为 0 时表示 $R_{0} $的数据无法输出到 B 端。
专用数据通路方式优缺点如下:
- 优点:基本不存在数据冲突的现象。
- 缺点:结构复杂,流量大,不易实现,只在特殊场合、需求中使用。
1.2.2.2.CPU 内部单总线(主要使用)
CPU 内部单总线:此种方式会将所有寄存器的输入和输出端都连接到一条公共的通路上。
- $R_{x}out $ 表示寄存器的输出控制信号, $ R_{x}in$ 表示寄存器的输入控制信号。
ALU 接受数据时也是通过总线接受,但这种方式会导致 ALU 无法分清这是哪一个操作数,所以我们可以在其中设置一个暂存寄存器。例如,下图中 $R_{0} $的数据会被先送到暂存寄存器上,然后使 $R_{0}out $ 失效,再导通 $R_{1}out \(,最后将\)R_{1} $数据输出到 B 端,这样的话就可以保证操作数的次序正确。
同时,暂存寄存器也可以避免破坏寄存器原有的内容。例如,某次运算两个操作数分别来自主存和 $R_{0} $,那么来自主存的操作数就可以直接放入暂存寄存器,而不用先放入 A,这样就避免了因 A 原本有内容而由于主存操作数的读入破坏了其内容的情况发生。
ALU 在计算完成之后仍然会将计算结果放回内部总线,不过这样做容易产生一个问题,一旦输入端发送的信号还没有稳定前,ALU 就产生了计算结果,并通过内部总线送回了寄存器,这样会导致运算错误。所以我们可以在 ALU 的输出端再加一个暂存寄存器,同时在暂存寄存器上方加一个三态门,等 ALU 输出结果稳定之后,让三态门导通,然后给寄存器加上电信号让输出结果送回寄存器即可。
1.3.控制器基本结构
1.3.1.控制器概述
控制器主要作用是取指令,分析指令和执行指令,主要涉及以下寄存器:
- 程序计数器 PC:用于指出下一条指令在主存中的存放地址。
- 指令寄存器 IR:用于保存当前正在执行的那条指令。
- 指令译码器:仅对操作码字段进行译码,向控制器提供特定的操作信号。
- 存储器地址寄存器:用于存放要访问的主存单元的地址。
- 存储器数据寄存器:用于存放向主存写入的信息或从主存读出的信息。
- 时序系统:用于产生各种时序信号,它们都是由统一时钟(CLOCK)分频得到。
- 微操作信号发生器:根据 IR 的内(指令)、PSW 的内容及时序信号,产生控制计算机系统的所需要的各种控制信号。
1.3.2.控制器控制过程概述
控制器控制过程概述:大致逻辑过程描述如下:
程序计数器 PC 会指明下一条指令的地址,当取出该指令后会将其放到指令寄存器 IR 当中。指令的地址码指明了操作数的地址信息,所以地址码的信息需要输出到内部总线上,而操作码部分会送给控制单元 CU。
具体来说,操作码会送给指令译码器 ,译码器的对应端会被选通,了解当前的指令类型后,就明白了下次执行的微操作是什么,所以译码器的输出信号会作为微操作信号发生器的输入信号,用于产生该指令的微操作序列。
微操作序列需要受到时序系统的控制。时序系统产生时序信号,微操作发生器每接受到一次信号,就会产生一个微操作(注意此时会受到 PSW 标志位的影响,有可能改变微操作的类型)。
最后还需要 MAR 和 MDR,MAR 连接地址总线,MDR 连接数据总线,用于和存储器进行交互。
1.4.CPU 的本质——寄存器的集合体
CPU 的本质就是寄存器的集合体,所以这也是 CPU 很贵的原因。
- 用户可见的寄存器:通用寄存器组、程序状态字寄存器 PSW,程序计数器 PC。
- 用户不可见的寄存器:MAR、MDR、IR 和暂存寄存器。
2.指令执行过程
2.1.指令周期是什么
指令周期:是指 CPU 从主存中取出并执行一条指令所需要的全部时间,不同指令的指令周期可能不同。指令周期常用若干机器周期(又叫 CPU 周期)来表示,一个机器周期又包含若干时钟周期(也称为节拍或 T 周期,T 是 CPU 操作的最基本单位)。
- 每个指令周期内的机器周期数可以不等。
- 每个机器周期内的时钟周期数可以不等。
机器周期指的是完成一个子过程所花费的时间,下图中的方波表示若干时钟周期。例如 CPU 取指令,它是一个程序化、步骤化的过程,所以需要花费多个时钟周期(对应多个操作)来完成。
不同指令的指令周期可能不同,例如:
- 空指令 NOP:空指令的意思就是什么也不做,因此其指令周期就是取指周期。
- 加法指令 ADD:指令周期包括取指和执行两个部分,且这个两个部分长度差不多。
- 乘法指令 MUL:相较于加法指令,由于乘法较为复杂,所以它的执行周期可能会更长。
- 具有间接寻址的指令:间接寻址需要多次访问主存才能取到真实的地址,因此它会多一个间址周期。
- 带有中断周期的指令:这种类型的指令会专门留出时间用于检测是否有中断信号,所以又会多一个中断周期。
2.2.指令周期流程
不同指令的指令周期可能不同,自然也会有不一样的执行流程。某个指令在执行过程中是否要经过某个周期需要进行判断。且这四个工作周期都会涉及到 CPU 的访存操作,只是访存的目的不同。
取指周期 (FE):为了取出指令。
间址周期 (IND)(可能有):为了得到有效地址。
执行周期 (EX):为了取得操作数。
中断周期 (INT)(可能有):为了保存程序断点 。
具体实现时可借助触发器完成,通过二进制位是否有效进行控制 。
2.2.1.取指周期
首先 PC 指明了当前要执行的指令在主存的存放地址,所以需要先把 PC 中的内容(指令地址)送入 MAR中,也即
(PC)->MAR
。因为取指令需要访问主存,所以 CU 通过控制总线向主存发出读信号, 也即
1->R
。MAR 中的地址信息会通过地址总线送给主存,读出相应数据后,该指令会通过数据总线送到 MDR 当中,也即
M(MAR)->MDR
。然后把 MDR 中的内容送入 IR 当中,也即
(MDR)->IR
。最后 CU 发出控制信号,让 PC+“1”,形成下一条地址,也即
PC=PC+1
。
总结:
(PC)->MAR
。1->R
。M(MAR)->MDR
。(MDR)->IR
。PC+1
。
2.2.2.间址周期
一旦指令采用间接寻址,就需要进入间址周期。
首先将指令的地址码送入 MAR,也即 Ad(IR)->MAR(注意也可以
Ad(MDR)->MAR
) 。CU 发出读控制信号,也即
1->R
。将 MAR 所指主存中的内容通过数据总线送入 MDR,也即
M(MAR)->MDR
。此时 MDR 保存的是操作数的有效地址。接下来 MDR 中的内容可以直接放入 MAR,也可以放入 IR 与原来的指令进行拼接(因为原来的地址只是形式地址)形成一个新的指令。
总结:
Ad(IR)->MAR
(也可以是Ad(MDR)->MAR
)。1->R
。M(MAR)->MDR
。
2.2.3.执行周期
执行周期的任务就是根据 IR 中指令字的操作码和操作数通过 ALU 产生执行结果,由于不同指令的执行周期操作不同,所以没有统一的数据流向。
2.2.4.中断周期
2.2.4.1.中断
中断:通俗理解就是暂停当前任务去完成其他任务,完成后返回。
例如,当前执行的程序由一些指令组成,现在执行到了指令 2,那么此时 PC 应该指向指令 3 。
指令 2 结束之后会进行中断检查,如果此时有中断信号过来,那么在指令 2 执行完毕之后,就要暂停当前程序,转而执行中断信号所对应的程序指令 。
执行完毕之后,再返回原来程序继续执行 。
2.2.4.2.中断周期
为了能够找到 “回家的路”,所以需要保存程序断点,其实也就是 PC 的值。一般使用堆栈来保存断点。下图 SP 表示栈顶指针,假设 SP 此时指向栈顶元素,进栈操作是先修改指针,后保存数据。
首先 CU 控制 SP,让其减 1,新指向的位置需要放入 PC。需要注意 SP 是堆栈指针,但其本质指向的是某个主存地址,所以它的意思就是现在需要把 PC 内的值放入 SP 所指向的某个主存单元保存起来,也即
(SP-1)->SP
,(SP)->MAR
。CU 通过控制总线向主存发出写信号,也即
1->W
。向 MAR 所指地址处写入 PC(断点)。一个数据想要写入主存,首先得放入 MDR。因此 (PC)->MDR,至此断点信息被保存 。
接下来就需要执行新的程序指令了,因此 CU 控制将中断服务程序的入口地址送入 PC,也就是把最上面示例图的 PC 指向改为指向 “X”,也即
向量地址->PC
。最后新的程序指令执行完成之后,依靠堆栈返回到之前的位置继续执行。
总之:
(SP-1)->SP
SP->MAR
1->W
(PC)->MDR
MDR->M(MAR)
向量地址 ->PC
2.3.指令执行方案
指令执行方案:一个指令周期通常要包括几个执行步骤,每个步骤完成指令的一部分功能,几个依次执行的步骤完成这条指令的全部功能。出于性能和硬件成本的考虑,可以选用如下三种不同的方案来安排指令的执行步骤:
- 单指令周期。
- 多指令周期。
- 流水线方案。
2.3.1.单指令周期
单指令周期:对所有指令都选用相同的执行时间来完成,称为单指令周期方案。
此时每条指令都在固定的时钟周期内完成,指令之间 串行执行,即下一条指令只能在前一条指令执行结束之后启动。因此指令周期取决于最长的指令的执行时间,对于那些本来可以在更短时间内完成的指令,也要使用这个较长的执行周期,会降低整个系统的运行速度。
2.3.2.多指令周期
多指令周期:对不同类型的指令选用不同的执行步骤来完成,称为多指令周期方案。
指令之间 串行执行,即下一条指令只能在前一条指令执行结束后启动。但是可以选用不同个数的时钟周期来完成不同指令的执行过程,指令需要几个周期就分配几个周期,而不再强求所有指令占用相同的执行时间。
2.3.3.流水线方案
流水线方案:指令之间可以并行执行的方案,称为流水线方案。
流水线方案力争 在每个时钟周期完成一条指令的执行过程(当然这只有在理想情况下才能达到)。这种方案通过在每个时钟周期启动一条指令,尽量让多条指令同时运行,但各自在不同的执行步骤。
3.数据通路单总线结构
3.1.有关概念
3.1.1.CPU 中数据的流动方式
一条指令的指令周期是会被划分为不同阶段,而不同阶段的数据流向也会不同,主要有以下三种:
- 寄存器和寄存器之间。
- 寄存器与主存之间。
- 寄存器与 ALU 之间。
3.1.2.数据通路和控制信号
数据通路:描述了数据在各个功能部件之间传送的路径。我们需要确定信息从哪里开始,中间经过哪些部件,最后又传至哪里。因此只要确定了数据的流向,我们就可以发出不一样的控制信号,来控制这些数据的流动。
控制信号是由控制部件产生的,虽然寄存器种类繁杂,但它们只会发出如下两类控制信号:
in
:也即输入路径。out
:也即输出路径。
这些信号都是由控制器发出的,所以下图中的 $ACC_{in} \(、\)ACC_{out} $、 $R0_{in} $和 $R0_{out} $等控制信号事实上和微操作发生器(CU)有着线路连接,微操作发生器发出不一样的信号就会使这些寄存器之间产生多种多样的联系。
3.1.3.数据通路种类
CPU 内部单总线(上图):该方式将所有寄存器的输入端和输出端都连接到同一条公共的通路上,这意味着同一时刻只允许两个部进行数据交换,它们对总线的使用是独占的。本小节探讨的内容所用的数据通路方式便是这种。
CPU 内部多总线方式:将所有寄存器的输入和输出端都连接到多条公共通路上。采用多总线方式,可以同时在多个总线上传送不同的数据。
专用数据通路方式:根据指令执行过程中的数据和地址的流动方向安排连接线路,避免使用共享的总线,性能高,但是硬件消耗量大。
3.1.4.内部总线与系统总线
- 内部总线:同一部件,如 CPU 内部连接各寄存器及运算部件之间的总线。
- 系统总线:同一台计算机系统的各部件,如 CPU、内存、通道和各类 I/O 接口间相互连接的总线。
以下的讲解中会使用这张图 。
3.2.寄存器之间的数据流动
例子:现在要把 PC 的内容送至 MAR,那么传送操作流程如下:
首先 $ PCout $有效(CU 发出信号),让其和总线导通 。
然后把 \(PC\) 的内容(其实就是电信号)送至 \(BUS\)(总线),也即 ( \(PC\))-> \(BUS\) 。
最后使 \(MAR_{in}\)有效, \(BUS\) 内容再送至 \(MAR\) 即可,也即 \(BUS\)-> \(MAR\) 。
在答题时一定要写清楚数据流向,最规范的模板为 。
3.3.主存与 CPU 之间的数据流动
例子:现在 CPU 要从主存中读取指令,那么传送操作流程如下:
首先,程序计数器 \(PC\) 指明了我们要读取的指令存放在什么地址,所以要把 \(PC\) 的内容放入 \(MAR\) 当中,即$ (PC)->Bus->MAR $(这一步其实也就是上面寄存器与寄存器之间的数据流动) 。
刚才,为了实现 PC 到 MAR 而使得 $PC_{out} $和 $PC_{in} $有效了,现在应该撤销这两个控制信号,让总线空闲。接下来要进行读操作,所以 CU 要向主存发出读信号,即 \(1-> R\)(注意该信号是通过控制总线发出的)。
然后使 \(MDR_{in}\) 有效(注意区分图中的 $MDR_{in} $, $MDR_{in} $是控制数据是否可以从内部总线流入 \(MDR\)),主存中对应地址信息的内容通过外部数据总线送入 \(MDR\) 当中,即 \(MEM(MAR)\)-> \(MDR\) 。
最后需要把该指令放入\(IR\) 当中, \(MDR->Bus->IR\) 。
较为规范的模板为:
3.4.寄存器与 ALU 之间的数据流动
执行算数或逻辑运算时数据可能会流向 ALU,比如现在要执行一条加法指令,加法运算的其中一个操作数已经被存放在 \(ACC\) 中了,另一个操作数地址会由加法指令直接指明。
首先需要根据该指令的地址码部分读取出参与加法的另一个操作数,即 $ Ad(IR) ->Bus-> MAR$,此时 $MDR_{out} $和 \(MAR_{in}\)有效。
当然还可以采用另外一种方式。之前就说过,取指令的时候是把指令先取到了 \(MDR\) 中然后再拷贝至\(IR\) 中,所以取指结束后, \(MDR\) 中也存放了这条指令的完整信息,因此可以直接把 \(MDR\) 中指令的地址码传送到 \(MAR\) 中,此时 $MDR_{out} $和 \(MAR_{in}\)有效。
CU 向主存发出读控制信号,即 $1-> R $
主存中相应信息通过外部数据总线送至 \(MDR\) 当中, \(MDR_{in}\) 有效,即 \(MEM(MAR)\)-> 数据总线 -> \(MDR\) 。
接下来把操作数放到暂存寄存器 \(Y\) 中,此时 $MDR_{out} $和 $ Y_{in} $有效,即 MDR->bus-> \(Y\)。之所以这样做是因为 ALU 必须同时接受到两个信号才可以运作,但是内部总线同一时刻只能传送一个输入信号,因此不得不把其中的一个操作放到暂存寄存器中,该寄存器与 ALU 是有一个专门的数据通路的,他们的传送不会占用内部总线 。
CU 向 ALU 发送加命令,然后 \(ACC_{out}\)和 $ALU_{in} $有效,执行加法操作,即 ( \(ACC\))+( \(Y\))->$ Z $。
当输出数据稳定之后,撤销 \(ACC_{out}\)和 $ALU_{in} $。最后将结果存回 \(ACC\) 中,即 $ Z-> ACC$ 。
较为规范的模板为 :
可以看出,通过发出不一样的控制信号,就能使微操作一步接着一步进行下去,每个微操作至少需要消耗一个时钟周期,每一个时钟周期内,CU 都会发出一组相应的控制信号来完成其中的某一个微操作。
3.5.有关 CPU 内部单总线经典例题
设有如下所示的单总线结构,请分支指令ADD
(R0),R1
的指令流程和控制信号。
- $R {1} \(表示源操作数(没有括号表示直接存放在寄存器中),\)(R {0} )$ 表示目的操作数(带有括号表示存储的操作数的地址,同时这两个操作数的运算的结果又会放回 $R {0} \(所指向主存单元)。也即\) ((R {0} ))+(R {1} )->(R 0{0} )$。
各个阶段的指令流程如下 :
1:取指周期:公共操作,都一样。
时序 | 微操作 | 有效控制信号 | 解释 |
---|---|---|---|
1 | (PC)->MAR | PCout,MARin | PC 所指指令地址送至 MAR |
2 | M(MAR)->MDR | MemR,MARout,MDRinE | 把指令送到 MDR 中 |
3 | (MDR)->IR | MDRout,IRin | 把指令由 MDR 送到 IR |
4 | 指令译码 | - | 进行译码操作 |
5 | (PC)+1->PC | - | PC+1 操作 |
2:间指周期:完成取数操作,被加数在主存中,加数已经存放在寄存器 \(R _{1}\)中了。
3:执行周期:此时加数在 R1 中,被加数在 Y 中。
注意:本节内容是计组考试中的高频考点,注意考察指令的执行过程。
4.数据通路专用通路结构
4.1.概述
如果数据通路采用 CPU 内部单总线,那么就意味着同一时间只允许两个部件进行数据交互。实际上,如果能使多个部件同时进行数据交互,那么指令的执行速度一定会的得到提升,实现这种需求一方面可以借助多总线的方式,另一方面还可以建立专用数据通路——在任何两个需要进行数据交互的部件之间建立数据通路。
如下:
取指周期如下:
4.2.例题
下图是一个简化了的 CPU 与主存连接结构示意图 (图中省略了所有的多路选择器)。其中有一个累加寄存器 (ACC)、一个状态数据寄存器和其他 4 个寄存器(MAR、MDR、PC 和 IR)。各部件及其之间的连线表示数据通路,箭头表示信息传递方向。
完成以下问题:
- 请写出图中 a、b、C、d 4 个寄存器的名称。
- 简述图中取指令的数据通路。
- 简述数据在运算器和主存之间进行存 / 取访问的数据通路。
- 简述完成指令 LDA X 的数据通路 (X 为主存地址,LDA 的功能为 (X)→ACC)。
- 简述完成指令 ADD Y 的数据通路 (Y 为主存地址,ADD 的功能为 (ACC)+ (Y)→ACC)。
- 简述完成指令 STA Z 的数据通路 (Z 为主存地址,STA 的功能为 (ACC)→Z)。
(1)请写出图中 a、b、C、d 4 个寄存器的名称。
首先 d 可以自动 “+1”,因此是 PC;PC 的内容是地址,送入 MAR,故 c 是 MAR;b 与微操作信号发生器相连,因此是 IR;相应的 a 就是 MDR。
- a:MDR
- b:IR
- c:MAR
- d:PC
(2)简述图中取指令的数据通路。
- (PC)->MAR
- M(MAR)->MDR
- MDR->IR
(3)简述数据在运算器和主存之间进行存 / 取访问的数据通路。
假设存 / 取的数据放到 ACC 中,并且数据地址已经放入 MAR 中。
取过程
- M(MAR)->MDR
- (MDR)->ALU->ACC
存过程
- (ACC)->MDR
- (MDR)->M(MAR)
(4)简述完成指令 LDA X 的数据通路 (X 为主存地址,LDA 的功能为 (X)→ACC)。
- X->MAR
- M(MAR)->MDR
- (MDR)->ALU->ACC
(5)简述完成指令 ADD Y 的数据通路 (Y 为主存地址,ADD 的功能为 (ACC)+ (Y)→ACC)。
- Y->MAR
- M(MAR)->MDR
- (MDR)->ALU,(ACC)->ALU
- ALU->ACC
(6)简述完成指令 STA Z 的数据通路 (Z 为主存地址,STA 的功能为 (ACC)→Z)。
- Z->MAR
- (ACC)->MDR
- (MDR)->M(MAR)
5.硬布线控制器
5.1.内容回顾和一些概念
高级语言编写的程序会被翻译为与之等价指令序列,每条指令的执行,有可能会涉及如下四个周期:
- 取指周期:完成取指令。
- 间指周期:如果采用间接寻址,需要将形式地址转变为真实地址。
- 执行周期:执行指令。
- 中断周期:处理中断信号。
下图中FE
、IND
、EX
和INT
分别是上面四个周期的缩写,各自对应了如下四个触发器,如果某个触发器为
1 就表示指令处于某个周期内。
一个指令周期内又需要若干微操作序列来完成该指令周期的工作,每个指令周期又由若干时钟周期组成(节拍),CU 会在每一个节拍内发出一个微命令,生成对应的微操作。
- 微命令和微操作是一一对应的:比如微命令 1 使得$ PC _{out}$ 、\(MAR _{in}\) 有效,完成对应的微操作 (PC)->MAR。
每个节拍内可以并行地完成互不冲突的微操作,而且同一个微操作也可能在不同指令的不同阶段被使用。
- 上图采用的是定长周期的策略(即便执行周期和中断周期可以在两个节拍内完成,但是我们还是让其耗时三个节拍)。
实际上,不同指令的执行周期所需要的节拍数是各不相同的,因此为了简化设计,选择定长的机器周期,以可能出现的最大节拍数为准(通常以访存所需要节拍数作为参考),若实际所需要节拍数较少,可以将微操作安排在机器周期末尾几个节拍上进行。
5.2.硬布线控制
硬布线控制:使用控制单元 CU 进行逻辑控制。
5.2.1.CU 如何发出微命令
可以看出,指令间区别最大的地方在于执行周期,像取指周期、间指周期和中断周期都是差不多的。所以,我们只要根据指令操作码、目前的指令周期、节拍信号以及机器状态条件就可以确定现在这个节拍下应该发出哪些微命令。具体来说:
STEP1:得让 CU 知道现在执行的是什么命令:首先需要把 IR 的 \(n\)位操作码送给操作码译码器( \(n\)位操作码意味着有 \(2 ^{n}\) 种不一样的指令,经过操作码译码器译码后对应的地址选择线就会被选通),CU 通过判断对应哪一个输入信号有效,来判断当前执行的是哪一条指令 。
STEP2:得让 CU 知道当前执行到了该指令的哪一个机器周期:所以需要把
FE
、IND
、EX
和INT
这四个触发器的二进制信息送给 CU,CU 通过判断对应的值是否为 1 来判断目前处于哪一个机器周期(需要注意这四个触发器实际上已经被集成在了 CPU 中) 。STEP3:得让 CU 知道当前处在该机器周期的哪一个节拍:因此需要给 CU 输入一个节拍信号,节拍信号是通过节拍发生器给出的,时钟部件会有规律的发出脉冲信号,每个脉冲信号就是一个时钟周期。节拍发生器在接受到时钟部件发出的信号后,就会让其中的某个输出线导通、节拍信号是循环发出的,当$ T _{m} $结束后,就会回到 \(T _{0}\),此时表示进入了新的机器周期 。
STEP4:最后需要给 CU 提供机器状态条件:状态条件统称为标志,它们来自于执行单元的返回信息。比如前面说过的来自于运算器的 PSW(溢出判断就在这里)、来自于 ACC 的符号位等,也有可能来自于 I/O 设备、主存等 。
这四组信息齐全后,CU 就可以给出当前节拍下应该发出的微命令:每个输出的控制信号对应一个微命令,也就是对应一个微操作。例如,如果$ C {1} $对应微操作为 $(PC) $->MAR,那么只需让其接到 \(PC _{out}\)和 $MAR {in} $即可 。
5.2.2.逻辑化表达式
现在最困难的问题在于:CU 如何能知道现在应该发出哪条命令?。比如上面的例子中,\(C _{1}\)被接通后就执行了 (PC)->MAR。
\(C _{1}\)的比较好解释:因为所有指令在取指周期内,第一步需要做的事情就是 (PC)->MAR。于是硬件工程师规定:无论是哪一种指令,只要处于取指周期(FE=1),同时还处于第一阶段($T {0} $)的话,就要完成 (PC)->MAR 这样的操作,也即是 \(C _{1}\)对应的操作,其对应的逻辑化表达式为 $C{1} $= $FE·T_{0} $ 。
说到这里大家可能就已经明白了,只要能写出某一个微命令对应的逻辑化表达式,然后设计相应的逻辑电路即可,但理想很美好,现实很骨感。上面那个例子的逻辑电路设计起来是非常简单的,而且最重要的是该微操作仅出现在取指周期的第一阶段;但有的微操作,例如 M(MAR)->MDR 它们使用的就非常频繁,那么他们应该怎么设计呢?这就是本节内容的核心。在学习硬件时大家要牢牢把握 “逻辑化表达式是电路的数学化描述” 这句话的深刻含义。
\(M(MAR)->MDR\) 的逻辑化表达式和电路如下图所示:
逻辑化表达式为: $FE· T_{1} +IND· T_{1} ( ADD+ STA+ LDA+ JMP+ BAN)+ EX·
T_{1}(ADD+LDA) $
$ FE· T_{1} $:与运算,如果结果为 1,就表示需要进行 M(MAR)->MDR 微操作 。
$EX· T_{1}(ADD+LDA) $:如果处在 ADD 加法命令或 LDA 命令的执行周期的 \(T_{1}\)阶段也表示需要进行 M(MAR)->MDR 微操作 。
5.3.硬布线控制器设计
- 注意:此部分内容在考试中基本不会涉及,但是对于理解硬布线控制却很有帮助。
5.3.1.硬布线控制器设计步骤
硬布线控制器设计步骤如下:
①:分析各个阶段的微操作序列(取指,间指,执行、中断)
- 确定哪些指令在什么阶段、在什么条件下会使用到的微操作。
②:选择 CPU 的控制方式
- 采用定长机器周期还是不定长机器周期?每个机器周期安排几个节拍?
- 注意:后面讲解采用同步控制方式(定长机器周期),一个机器周期内安排 3 个节拍。
③:安排微操作时序
- 如何用 3 个节拍完成整个机器周期内的所有微操作。
④:电路设计
- 确定微操作命令的逻辑表达式,并用电路实现。
5.3.2.步骤一:分析各个阶段的微操作序列
如果我们能罗列出某个系统在各个阶段的微操作序列,就可以知道在什么情况下需要使用到这个微操作。
取指周期(所有指令都一样)。
- PC->MAR
- 1->R
- M(MAR)->MDR
- MDR->IR
- OP(IR)->ID(ID 是指令译码器)
- (PC)+1->PC
间址周期(所有指令都一样)。
- Ad(IR)->MAR(找寻真正地址)
- 1->R
- M(MAR)->MDR
- MDR->Ad(IR)
执行周期(各不相同),例如:
CLA:clear ACC 指令、ACC 清零。
- 0->ACC
LDA X:取数指令,把 X 所指内容取到 ACC。
- Ad(IR)->MAR
- 1->R
- M(MAR)->MDR
- MDR->ACC
JMP X:无条件转移。
- Ad(IR)->PC
BAN X:条件转移,当 ACC 为负时转移(属于机器状态条件)。
- \(A_{0}⋅Ad(IR)+ \overline A_{0}⋅(PC)->CP\)
5.3.3.步骤三:安排微操作时序
- 注意:第二步已经完成,我们会采用定长机器周期,并且每个机器周期内安排三个节拍。
安排微操作时序有如下原则:
- 原则一:微操作的先后顺序不得随意更改(比如 PC->MAR 一定在 M(MAR)->MDR 之前完成)。
- 原则二:被控对象不同的微操作尽量安排在一个节拍内完成(比如 PC->MAR 控制对象为寄存器,1->R 控制对象为主存,因此尽量安排在同一个节拍内完成)。
- 原则三:占用时间较短的微操作尽量安排在一个节拍内完成,并允许有先后顺序(比如寄存器之间的交互快于寄存器与主存的交互,因此如果可以的话尽量将其放在一个节拍完成)。
比如取指周期,上面得到的微操作序列,在这种原则下是不合适的,因此更改如下:
- PC->MAR 和 1->R 由于被控对象不同的,所以放在一个节拍内。
- (PC+1)->PC 位置随意,只要在 PC->MAR 之后即可,所以搭配一个 M(MAR)->MDR 让其在一个节拍内进行。不把 M(MAR)->MDR 放在后面的原因是因为这是从主存取数据,时间较长,起码得保证一个时钟周期。
- 后面两个是 CPU 内部寄存器的数据传送,因此速度很快,在一个时钟周期内是可以一次同时发出两个微命令的。
间址周期安排如下:
执行周期的设计可以说是整个设计的核心所在,不同指令的执行周期千差万别,具体如何设计是硬件工程师的任务,在这里我们只是简单了解即可。主要是想让大家明白一点,指令的设计是一个非常严谨的事情,它有哪几个周期,一个周期内有几个节拍,一个节拍要完成哪些微操作,这些都是必须要考虑到的事情。
- 设计时会将指令分为非访存,访存和转移指令等。
5.3.4.步骤四:组合逻辑设计(电路设计)
①:列出操作时间表:也即列出在取指、间址、执行和中断周期, \(T_{0}\)、 \(T_{1}\)和 \(T_{2}\)节拍内有可能用到的所有微操作
对于取指周期:
- 需要用到该微操作的填 “1”,否则空
- 注意表格中的状态条件栏:如果填 “ $
I$”,表示该指令采用间接寻址,需要将间址特征送入,即 1->IND;如果填 “
$I $”,表示该指令将直接进入执行周期,即
1->EX
。
对于间址周期:
注意状态条件栏:如果填 " $ I N D $",表示该指令采用多级间接寻址,直到该状态栏不填任何信息时,才表示结束了间接寻址,可以进入执行周期 。
③对于执行周期:
②:写出微操作命令的最简表达式。
从上面的表格中我们可以看到 M(MAR)->MDR 操作的使用频次。
- 对于取指周期,只要处在 \(T_{1}\),无论哪一个指令都要用到 M(MAR)->MDR,故为 \(FE\)· \(T_{1}\)+ \(IND\)· \(T_{1}\)( \(ADD\)+ \(STA\)+ \(LDA\)+ \(JMP\)+ $BAN $)+ \(EX\)· \(T_{1}(ADD+LDA)\)。
- 对于间址周期,只要处在 \(T_{1}\),并且是 \(ADD\)、 \(STA\)、 \(LDA\)、 \(JMP\) 。 、 $BAN $ 指令的话,就要用到 M(MAR)->MDR,故为 \(FE\)· \(T_{1}\)+ \(IND\)· \(T_{1}\)( \(ADD\)+ \(STA\)+ \(LDA\)+ \(JMP\)+ $BAN $)+ \(EX\)· \(T_{1}(ADD+LDA)\)。
- 对于执行周期,只要处在 \(T_{1}\),并且是 \(ADD\) 或 \(LDA\) 的话,就要用到
M(MAR)->MDR
,故为 \(FE\)· \(T_{1}\)+ \(IND\)· \(T_{1}\)( \(ADD\)+ \(STA\)+ \(LDA\)+ \(JMP\)+ $BAN $)+ \(EX\)· \(T_{1}(ADD+LDA)\)。
综上,当逻辑表达式:“ \(FE\)· \(T_{1}\)+ \(IND\)· \(T_{1}\)( \(ADD\)+ \(STA\)+ \(LDA\)+ \(JMP\)+ $BAN $)+ \(EX\)· \(T_{1}(ADD+LDA)\)” 为 1
时,就要执行M(MAR)->MDR
微操作。
③:设计出逻辑表达式对应的电路图:
5.4.总结
硬布线控制器的设计步骤如下:
1:分析每个阶段的微操作序列 。 2:选择 CPU 的控制方式 。 3:安排微操作时序 。 4:电路设计。
- 列出操作时间表。
- 写出微操作命令的最简表达式。
- 画出逻辑图。
硬布线控制器的特点:
- 指令越多,设计和实现就越复杂,因此一般用于 RISC(精简指令集系统)。
- 如果扩充一条新的指令,则控制器的设计就需要大改,因此扩充指令困难。
- 由于使用纯硬件实现控制,因此执行速度很快(微操作控制信号由组合逻辑电路即时产生)。
6.微程序控制器的基本原理
硬布线控制器,就是用纯硬件实现的控制器,电路非常复杂,也是整个计组中的难点之一,好在考试基本不考,而本节需要学习的微程序控制器倒是在大题中常有出现。
6.1.微程序控制器的设计思路
- 程序会被翻译为对等的机器指令。
- 机器指令又会被分为一个个的微操作序列。
微程序控制器的设计思路:把每条机器指令编写成一个微程序,每个微程序包含若干微指令,每条微指令对应一个或几个微操作命令。所以微指令之于指令就等价于指令之于程序。
- 指令是对程序执行步骤的描述。
- 微指令是对指令执行步骤的描述。
- 微命令与微操作一一对应。
- 微指令可能包含多个微命令(微操作)。
比如下图中的微指令 d,它指明了 “完成微操作 5、2”。
每条指令对应一个微程序,这些微程序可以存到一个控制存储器中,用程序机器指令的办法来寻址每个微程序中的微指令。目前,大多计算机都采用微程序设计技术。
其中,存放微指令的控制存储器的单元地址称为微地址,一条微指令通常包含:
- 操作控制字段:又称操作码字段,用于产生某一步操作所需要的各种操作控制信号。
- 顺序控制字段:又称微地址码字段,用于控制产生下一条要执行的微指令地址。
6.2.微程序控制器的基本结构
6.2.1.微程序控制器基本组成
微程序控制器基本组成:
控制存储器 CM: 它是微程序控制器的核心部件,用于存放各指令对应的微程序,使用只读存储器 ROM 构成。每一条机器指令对应的微指令序列,由 CPU 厂商负责设计,并且在 CPU 出厂之前就已经把 ROM 里面的微程序数据全部写好了。
微地址形成部件: 由于不同指令对应的微程序是不同的,因此需要根据该指令的操作码来确定它所对应的微程序的起始地址,以保证微指令的连续进行。
微地址寄存器 CMAR: 有 MAR 就有 CMAR,和 MAR 一样,它用于接收微地址形成部件送来的微地址;同时 CMAR 还有一个别名,叫做 u u uPC,其实就是把 PC 和 MAR 整合到了一起。
地址译码器: 有了地址就需要地址译码器,地址译码器会把地址码转换为存储单元控制信号。
微指令寄存器 CMDR: 有 MDR 就有 CMDR,它是微指令寄存器,别名叫做 u u uIR,用于存放从 CM 中取出的微指令,它的位数同微指令的字长。
顺序逻辑控制单元。
6.2.1.微程序控制器工作过程
微程序控制器基本组成:当 CPU 取到一条指令之后,流程如下:
- 把指令的操作码送给微地址形成部件,以确定微指令序列的起始地址。
- 根据顺序逻辑及其他标志信息等来确定接下来要执行的微指令的地址。
- 将微指令地址放入到 CMAR 中。
- 经过地址译码器译码后就可以选中 CMAR 所指向的微指令。
- 取出该微指令,存放到 CMDR 中。
- (执行完该微指令后需要把微指令 “下地址” 信息送给顺序逻辑,结合其他信息用于判断下一个微指令)。
- 硬件电路需要根据该微指令的控制码部分,向 CPU 内部其他部件或系统总线发出控制信号(\(PC_{out} ,MAR _{in}\),\(1->R\) 等等)。
6.3.微程序控制器的工作原理
所有指令的取指周期、间址周期和中断周期几乎是一样的,所以这几个周期所对应的微指令序列也是可以共享的,因此在 CM 中只会存储一份。
取指周期的微程序段通常是公用的,所以 如果某指令系统中有 n 条机器指令,则 CM 中微程序段的个数至少是 n+1 个,而对于一些早期的 CPU,物联网设备的 CPU 由于其 CPU 可以不包含间址周期和中断周期,所以不包含进去。
需要注意:物理上取指周期、执行周期看起来像两个微程序,但逻辑上应该将其看作一个整体。因此,“一条指令对应一个微程序” 的说法是正确的。
7.微指令的设计
7.1.微指令的格式
7.1.1.水平型微指令
水平型微指令:是指一条微指令可以定义多个可并行执行的微命令。
- 优点: 微程序短,执行速度快。
- 缺点: 微指令长,编写微程序较为麻烦。
水平型微指令其操作控制码部分较长,如果采用水平型微指令,那么指令的条数较少(一条微指令可以完成多个微操作或微命令),所以指令体积就会感觉很 “胖”。
7.1.2.垂直型微指令
垂直型微指令:是指一条微指令只能定义一个微命令,由微操作码字段规定具体功能。
- 优点:微指令短、简单、规整、便于编写微程序。
- 缺点:微程序长,执行速度慢,工作效率低。
垂直型微指令其操作控制码部分短,如果采用垂直型微指令,那么指令的条数较多(一条微指令只能定义一个微操作或微命令),所以指令体积就会感觉很 “瘦”。
7.1.3.混合型微指令
混合型微指令:在垂直型的基础上增加一些不复杂的并行操作。微指令较短,仍便于编写,形成的微程序也不长,执行速度加快。
7.2.微指令的编码方式
微指令的编码方式:又称为微指令的控制方式,它是指如何对微指令的控制字段进行编码,以形成控制信号。编码的目的是在保证速度的情况下,尽量缩短微指令字长。
7.2.1.直接编码(直接控制)
直接编码:直接编码无需译码,在微指令的操作控制字段中,每一位代表一个微命令。设计微指令时,选用或不选用某个微命令,只要将表示该微命令的对应位设置为 1 或 0 即可,每个微命令对应并控制数据通路中的一个微操作。
- 优点:简单、直观、执行速度快、操作并行性好。
- 缺点:微指令字长过长,n 个微指令就要求微指令的操作字段有 n 位,造成控制存储器容量变得很大。
- 上图表示发出 (PC)->MAR 和 1->R 信号。
7.2.2.字段直接编码
字段直接编码:将微指令的微命令字段分成若干小字段,然后把互斥性微命令组合在同一字段中,把相容性微命令组合在不同字段中。
- 互斥性微命令:不能并发执行(比如 PC->MAR 和 PC+1->PC)。
- 相容性微命令:可以并发执行(比如 PC->MAR 和 1->R)。
每个字段独立编码,每种编码代表一个微命令且各字段编码含义单独定义,与其他字段无关 。
微命令字段分段的原则为:
- 互斥性微命令分在同一段内,相容性微命令分在不同段内。
- 每个小段中包含的信息位不能太多,否则将增加译码线路的复杂性和移码时间。
- 一般每个小段还要留出一个状态,表示本字段不发出任何微命令。因此当某字段的长度为 3 位时,最多只能表示 7 个互斥的微命令,通常 000 表示不操作。
字段直接编码优缺点如下
- 优点:可以缩短微指令字长。
- 缺点:由于要通过译码电路后再发出微命令,因此比直接编码要慢。
7.2.3.字段间接编码
字段间接编码:一个字段的某些微命令需要用另一个字段中的某些微命令解释,由于不是靠字段直接译码发出的微命令,因此称为字段间接编码,又称隐编码。
- 优点:可以进一步缩短微指令字长。
- 缺点:削弱了微指令的并行控制能力,所以通常作为字段直接编码的一种辅助手段。
7.3.微指令的地址形成方式
7.3.1.下地址给出
下地址给出:下一个微指令的地址直接由当前微指令的下地址字段指出。
7.3.2.操作码形成
操作码形成:当机器指令取至指令寄存器之后,微指令的地址由操作码经微地址形成部件形成。
7.3.3.增量计数法
增量计数法:类似于 (PC+1)->PC,有 (CMAR+1)->CMAR。
7.3.4.分支转移
有些微指令是转移指令,类似于 JMP。
7.3.5.通过测试网络
7.3.6.由硬件产生微程序入口地址
- 第一条微指令地址:由专门硬件产生(用专门的硬件记录取指周期微程序首地址)。
- 中断周期:由硬件产生中断周期微程序首地址(用专门的硬件记录)。
8.微程序控制单元的设计
8.1.微程序控制单元设计步骤
8.1.1.第一步:分析每个阶段的微操作序列
无论是组合逻辑设计还是微程序设计,对于相同的 CPU 结构,两种控制单元的位操作码和节拍安排都是极其相似的。以微程序控制单元在取指阶段发出的微操作命令及节拍安排如下:
- \(T_{0}\):PC->MAR,1->R(对应微指令 a)。
- \(T_{1}\):M(MAR)->MDR,PC+1->PC(对应微指令 b)。
- \(T_{2}\):MDR->IR,OP(IR)-> 微地址形成部件(对应微指令 c)。
相比于硬布线控制,只是在 \(T_{2}\)节拍内的微操作命令有所不同:微程序控制单元在 \(T_{2}\)节拍内要将指令的操作码送至微地址形成部件(OP(IR)-> 微地址形成部件),以形成该条机器指令的微程序首地址。而硬布线控制单元在 \(T_{2}\)节拍内要将指令的操作码送至指令译码器,以控制 CU 发出相应的微命令(OP(IR)->ID)。
若把一个节拍 \(t\) 内的微操作安排在一条微指令中完成,上述微操作就对应了 3 条微指令。但是由于微程序控制的所有控制信号都来自于微命令,而微命令又存在于控制存储器中,因此欲完成这些微操作,必须先将微指令从控制存储器中读出,即必须先给出这些微指令的地址。
- 在取指微程序中,除第一条微指令外,其余微指令的地址均由上一条微指令的下地址字段直接给出,因此上述每条微指令都需要增加一个将微指令下地址字段送至 CMAR 的微操作,也即 Ad(CMDR)->CMAR。
- 取指微程序的最后一条微指令,其后继微指令的地址是由微地址形成部件形成的,即微地址形成部件 ->CMAR。为了反映该地址与操作码有关,因此记为 OP(IR)-> 微地址形成部件 ->CMAR。
总之,考虑到需要形成后继的微指令地址,上述取指操作应需要 6 条微指令:
- \(T_{0}\):PC->MAR,1->R
- \(T_{1}\):Ad(CMDR)->CMAR
- \(T_{2}\):M(MAR)->MDR,(PC+1)->PC
- $T_{3} $:Ad(CMDR)->CMAR
- $T_{4} $:MDR->IR
- $T_{5} $:OP(IR)-> 微地址形成部件 ->CMAR
8.1.2.第二步:写出对应机器指令的微操作命令及节拍安排
首先写出每个周期所需要的微操作,也就是把可以并行的微操作安排在同一时序进行,这一点请参照:5.硬布线控制器。
安排微操作时序有如下原则:
- 原则一:微操作的先后顺序不得随意更改(比如PC->MAR一定在M(MAR)->MDR之前完成)
- 原则二:被控对象不同的微操作尽量安排在一个节拍内完成(比如PC->MAR控制对象为寄存器,1>R控制对象为主存,因此尽量安排在同一个节拍内完成)
- 原则三:占用时间较短的微操作尽量安排在一个节拍内完成,并允许有先后顺序(比如寄存器之间的交互快于寄存器与主存的交互,因此如果可以的话尽量将其放在一个节拍完成)
比如取指周期,上面我们所列的微操作序列,在这种原则下是不合适的,因此更改如下:
另外还要加入一些特有的操作:
取指周期内,除了最后一条微指令,每一条微指令结束后都要根据当前微指令的下地址字段指出下一条微指令的地址,即 Ad(CMDR)->CMAR;取指周期的最后一条微指令执行完成之后,要根据指令操作码确定其执行周期的微程序首地址,即 OP(IR)-> 微地址形成部件 ->CMAR。
执行周期内,每一条微指令结束后都要根据当前微指令的下地址字段指出下一条微指令的地址,即 Ad(CMDR)->CMAR;执行周期最后一条微指令其下地址是 0,又会指向取指周期第一条微指令 。
8.1.3.第三步:确定微指令格式
- 根据微操作个数决定采用何种编码方式,以确定微指令的操作控制字段的位数。
- 根据 CM 中存储的微指令总数,确定微指令的顺序控制字段的位数。
- 最后按操作控制字段位数和顺序控制字段位数就可以确定微指令字长。
更多细节请看7.微指令的设计。
8.1.4.第四步:编写微指令码点
根据操作控制字段每一位代表的微操作命令,编写每一条微指令的码点。
8.2.微程序设计分类
8.2.1.静态微程序设计和动态微程序设计
- 静态:微程序无需改变,采用 ROM。
- 动态:通过改变微指令和微程序改变机器指令,有利于仿真,采用 DPROM。
8.2.2.毫微程序设计
- 微程序设计:使用微程序解释机器指令。
- 毫微程序设计:使用毫微程序解释微程序。
8.3.硬布线控制器和微程序控制器比较
微程序控制器 | 硬布线控制器 | |
---|---|---|
工作原理 | 微操作控制信号以微程序的形式存放在控制存储器中,执行指令时读出即可 | 微操作控制信号由组合逻辑电路根据当前的指令码,状态和时序即时产生 |
执行速度 | 慢 | 快 |
是否规整 | 是 | 否 |
应用场合 | CISC 和 CPU | RISC 和 CPU |
易扩充性 | 易于扩充 | 很难扩充 |
9.中断和异常
9.1.中断的作用
在操作系统引入核心态和用户态这两种工作状态后,就需要考虑它们之间的切换问题了。具体来讲,操作系统内核工作在核心态,用户程序工作在用户态,系统不允许用户程序使用核心态的功能,但是用户程序为了完成某些操作又必须使用这些功能。
- 比如 C
语言中的
printf
可以向屏幕打印一些内容。在屏幕上显示内容,这本就是操作系统才能做到的事情,所以你编写的程序在运行必须使用相关功能。
#include <stdio.h>
int main()
{
printf("hello world\n");
return 0;
}
因此,需要在核心态建立一些 “门”,以便实现从用户态进入核心态。而中断就是 CPU 运行上层程序时唯一能进入这些 “门” 的途径,同时中断也是让操作系统内核夺回 CPU 使用权的唯一途径。发生中断时,用户态会立即进入核心态,这是通过硬件实现的。
9.2.中断的类型
9.2.1.外中断(中断)
中断:也称为外中断,指中断信号来自于 CPU 外部,也即与当前执行的指令无关,例如:
时钟部件会每隔一个时间片给 CPU 发送一个时钟中断信号,防止某些程序长时间抢占 CPU。
输入 / 输出处理完成后,相关设备也会发送一个中断信号,希望处理机能够向设备发下一个输入 / 输出请求,同时让完成输入 / 输出后的程序继续运行 。
9.2.2.内中断(异常)
内中断:也称为异常 (trap),指中断信号来自于 CPU 内部,也即与当前执行的指令有关,例如:
- 试图在用户态下执行特权指令。
- 执行除法指令时发现除数为 0。
- 应用程序想要请求操作系统内核为其提供服务,此时会执行一条特殊的指令——陷入指令(
trap
),该指令会引发一个内中断信号(比如 C 语言中的printf
)。
对异常的处理一般要依赖于当前程序的运行现场,而且异常不能被屏蔽,一旦出现异常应立即处理。
9.3.中断的处理过程
此部分内容需要用到大量计组的知识,不是三言两语就能说清楚的,这里只是简单谈及,读者可以查阅文章最开始的链接进行学习 。
关中断:在中断服务程序中,为了保护中断现场 (即 CPU 主要寄存器中的内容) 期间不被新的中断所打断,必须关中断,从而保证被中断的程序在中断服务程序执行完毕后能接着正确地执行。
保存断点:为保证在中断服务程序执行那个完毕后能正确地返回原来的程序,必须将原来程序的断点(即 PC 的内容)保存起来。这一点我们在2.指令执行过程中有过详细介绍。
引出中断服务程序:其实质是取出中断服务程序的入口地址并传送给程序计数器 PC。
保护现场: 保存通用寄存器和状态寄存器的内容(即保存 ACC 寄存器的值),以便返回原程序后可以恢复 CPU 环境,可以使用堆栈,也可以使用特定存储单元。
中断服务: 主体部分,如通过程序控制需打印的字符代码送入打印机的缓冲寄存器 (中断服务的过程中有可能会修改 ACC 寄存器的值)。
恢复现场: 通过出栈指令或取数指令把之前保存的信息送回寄存器中(把原程序算到一般的 ACC 值恢复原样)。
中断返回:通过中断返回指令回到原程序断点处。
10.指令流水线基本概念性能指标
10.1.指令流水的定义
前面说过,一条指令的执行过程可以分成多个阶段,不同的计算机有不同的分法,其中比较通用的划分方法就是划分为取指,分析和执行三个阶段。
取指:根据 PC 内容访问主存储器,取出一条指令送到 IR 中。
分析:对指令操作码进行译码,按照给定的寻址方式和地址字段中的内容形成操作数的有效地址 EA,并存有效地址 EA 中取出操作数。
执行:根据操作码字段完成指令规定的功能,即把运算结果写入到通用寄存器或主存中 。
当多条指令在处理器中执行时,会有如下三种执行方式,称之为指令流水:
- 顺序执行
- 一次重叠
- 二次重叠
10.1.1.顺序执行方式
顺序执行方式:指令会按顺序执行,前一条指令执行完之后,才启动下一条指令。传统的冯诺依曼机便采用此种方式,又称其为串行执行方式。
- 优点:控制简单,硬件代价小。
- 缺点:执行指令的速度较慢,任何时刻,处理机中只有一条指令在执行,各功能部件利用率很低。
设取指、分析、执行 3 个阶段的时间都相等,用 \(t\) 表示,那么顺序执行 \(n\)条指令所用时间为 $T=3nt $。
10.1.2.一次重叠方式
一次重叠方式:同时进行第 k 条指令的 “执行阶段” 和第 k+1 条指令的 “取指阶段”。
- 优点:程序的执行时间缩短了 $ $,各功能部件的利用率明显提高。
- 缺点:需要付出较大的硬件代价,控制过程也比顺序执行复杂。
采用此种方式时,执行 \(n\)条指令所用时间为:
$T=3t+(n-1)×2t=(1+2n)t $
10.1.3.二次重叠执行方式
二次重叠方式:为了进一步提高指令的执行速度,可以把 “取 \(K\)+1 条指令” 提前到 “分析第 \(K\) 条指令”的期间完成,使 “分析第 k+1 条指令” 与“执行第 k 条指令”同时进行。
- 优点:使指令的执行时间缩短了近 2/3。
采用此种方式,执行 \(n\)条指令所用时间为:
$T=3t+(n-1)×t=(2+n)t $
这是一种理想的指令执行方式,在正常情况下,处理机中同时有 3 条指令在执行. 若每条指令需要通过 4 个或 5 个执行步骤完成,则可以采取 3 次或 4 次重叠执行方式(考试常考 5 次)。
10.2.流水线的表示方法
10.2.1.指令执行过程图
指令执行过程图:该图用于描述指令的执行过程以及影响流水线的因素,横坐标表示时间、纵坐标表示指令序列。
10.2.2.时空图
指令执行过程图:在时空图中,横坐标表示时间(输入流水线中的各个任务在流水线中所经过的时间);纵坐标表示空间,即流水线的每个流水段(对应各个执行部件)。
- 从上图中可以看出,第一条指令 \(I_{1}\)在时刻 \(t_{0}\)进入流水线,在时刻$ t_{4}$流出流水线。
- 第二条指令$I_{2} $在时刻 \(T_{1}\)进入流水线,在时刻 \(t_{5}\)流出流水线。
- 以此类推,每经过一个Δt 时间,便有一条指令进入流水线,从时刻$ t_{4}$开始有一条指令流出流水线。
10.3.流水线性能指标
10.3.1.吞吐率
吞吐率:是指在单位时间内流水线所完成的任务数量,或是输出结果的数量。
假设任务数为 n n n,处理完这 \(n\)个任务所用时间为 $ T_{k}$,则计算流水线吞吐率( $ TP$)的最基本公式为
$ TP= $
对应时空图如下:
一条指令的执行分为 \(K\) 个阶段,每个阶段耗时Δt,一般取Δt = 一个时钟周期 。
则流水线的实际吞吐率为:
$TP= $
当连续输入 \(n\)趋向于无穷时就有:
$ _{n }TP= $
故:
$ TP_{max}= $
10.3.2.加速比
加速比:完成同样一批任务,不使用流水线所用的时间与使用流水线所用的时间之比
设 \(T_{0}\)表示不使用流水线时的执行时间,即顺序执行所有指令花费的时长; $ T_{k}$表示使用流水线的执行时间,则计算流水线加速比 $S $ 的基本公式为
$S= $
单独完成一个任务耗时为 $ kt$,则顺序完成 \(n\)个任务耗时为 $ T_{0}=nk$,且 $ T_{k}=(k+n-1)$,故实际加速比为:
$ S== $
当连续输入 \(n\)趋向于无穷时就有:
$ _{n }S= $
故:
$ S_{max}=k $
10.3.3.效率
加速比:流水线的设备利用率称为流水线的效率。在时空图上,流水线的效率定义为: \(n\)个任务占用的时空区有效面积与 \(n\)个任务所用的时间与 \(K\) 个流水段所围成的时空区域总面积之比。
则流水线效率 ( \(E\)) 的一般公式为:
$ E== $
当连续输入 \(n\)趋向于无穷时就有:
$ _{n }E= $
故:
$ E_{max}=1 $
11.指令流水线影响因素分类
11.1.影响指令流水线的因素
10.指令流水线基本概念性能指标中所讲到的流水线都是理想情况,但在实际情况中流水线的衔接似乎不那么完美,那么这当中的影响因素都有哪些呢?
11.1.1.结构相关(资源冲突)
11.1.1.1.概述
结构相关(资源冲突):由于多条指令在同一时刻争用同一资源而形成的冲突称为结构相关。
如下图所示,Load
指令在进入Mem
阶段时,Instr3
指令才刚进入取指阶段,两者都会访问主存所以可能导致资源上的冲突。
11.1.1.2.解决方法
结构相关(资源冲突)解决方法:
第一种解决方法:后一相关指令暂停一周期。
第二种解决方法:进行资源重复配置,专门设立数据存储器和指令存储器,使访问数据和访问指令专属于不同的存储块,互不干扰 。
11.1.2.数据相关(数据冲突)
11.1.2.1.概述
数据相关(数据冲突):在一个程序中,如果存在必须等前一条指令执行完才能执行后一条指令的情形,则这两条指令为数据相关。
如下图所示,众多指令在依次执行。sub
、and
、or
和xor
这些指令都会用到r1
这个操作数。其中add
指令会把r2
和r3
相加的结果放入r1
,在这个过程中,如果and
后面的指令在and
指令还没有把r1
放入内存时就访问了r1
,那么就会导致sub
、and
和or
这三个指令拿到错误的r1
,而只有xor
拿到了正确的r1
。
11.1.2.2.解决方法
数据相关(数据冲突)解决方法。
第一种解决方法:把遇到数据相关的指令及其后续指令都暂停一至几个时钟周期,直至数据相关问题消失后再继续进行,可以分为 硬件阻塞 (stall) 和 软件插入 "NOP" 两种方法 。
第二种解决方法:使用数据旁路技术,仔细观察,
r1
的正确结果其实已经在执行阶段结束之后就生成了,因此可以把该指令的计算结果作为 ALU 的一个输入来源,直接开始计算过程 。第三种解决方法:使用编译优化,通过编译器调整指令顺序,使得一些不需要该数据的后续指令先于这些指令执行。
11.1.3.控制相关(控制冲突)
11.1.3.1.概述
控制相关(控制冲突):当流水线遇到转移指令和其他改变 PC 值的指令而造成断流时,会引起控制相关、
11.1.3.2.解决方法
控制相关(控制冲突)解决方法:
- 转移指令分支预测:简单预测(永久 true 或者 false)、动态预测(根据历史情况)动态调整。
- 预期转移成功和不成功两个控制流方向上的目标指令。
- 加快和提前形成条件码。
- 提高转移方向的猜准率。
11.2.流水线的分类
11.2.1.根据流水线使用的级别不同分类
部件功能级流水:就是把复杂的算数逻辑运算组成流水线工作方式。例如可以把浮点加法操作分为求阶、对阶、尾数相加以及规格化 4 个子过程。
处理机级流水:就是把一条指令解释过程分为多个子过程。例如我们经常提到的取指、译码、执行和访存及写回 5 个子过程。
处理间流水:就是一种宏流水,其中每一个处理机完成某一专门任务,各个处理机所得到的结果需要存放在与下一个处理器所共享的存储器中。
11.2.2.根据流水线可以完成的功能分类
单功能流水线:只能实现一种固定的专门功能的流水线。
多功能流水线:通过各段间的不同连接方式可以同时或不同时地实现多种功能的流水线。
11.2.3.根据同一时间内各段之间的连接方式
静态流水线:在同一时间内,流水线的各段只能按同一种功能的连接方式工作。
动态流水线:在同一时间内,当某些段正在实现某种运算时,另一些段正在进行另一种运算。这样对提高流水线的效率很有好处,但会使流水线控制变得很复杂。
11.2.4.根据流水线的各个功能段之间是否有反馈信号
线性流水线:从输入到输出,每个功能段只允许经过一次,不存在反馈回路。
非线性流水线:存在反馈回路,从输入到输出过程中,某些功能段将数次通过流水线,这种流水线适合进行线性递归的运算。
11.3.流水线多发技术
11.3.1.超标量技术
超标量技术:每个时钟周期内可以并发执行多条独立指令,即以并行操作方式将两条或多条指令编译并执行,为此需要配置多个功能部件。超标量计算机不能调整指令的执行顺序,因此通过编译优化技术,把可并行执行的指令搭配起来,挖掘更多的指令并行性。
11.3.2.超流水技术
超流水技术:在一个时钟周期内再分段,在一个时钟周期内一个功能部件使用多次。不能调整指令的执行顺序,靠编译程序解决优化问题。
11.3.3.超长指令字
超流水技术:由编译程序挖掘出指令间潜在的并行性,将多条能并行操作的指令组合成一条具有多个操作码字段的超长指令字(可以达到上百位),为此需要采用多个处理部件。
12.五段式指令流水线
本节会介绍如下 5 类指令的执行过程,它们在考试中经常出现:
- 运算类指令
- LOAD 指令
- STORE 指令
- 条件转移指令
- 无条件转移指令
指令在执行过程中会涉及如下过程:
IF
:取指ID
译码 & 取数EX
执行M
:访存WB
:写回寄存器
注意:
- 在 RISC 处理器中只有 LOAD 和 STORE 才能访问主存。
- 转移类指令通常采用相对寻址(相对于 PC)。
12.1.运算类指令的执行过程
下表展示了 2 个较为典型的运算类指令:
加法指令(另个寄存器相加) | ADD Rs,Rd | (Rs)+(Rd)-> Rd |
加法指令(寄存器与立即数相加) | ADD #996,Rd | 996+(Rd)-> Rd |
算数左移指令 | SHL Rd | (Rd)<<<2-> Rd |
运算类指令步骤一(IF
):根据 PC 从指令 Cache
取指令到 IF 段的锁存器。
运算类指令步骤二(ID
):取出操作数到 ID
段的锁存器。
- ADD Rs,Rd:Rs 放到 \(A\)中、Rd 放到 \(B\) 中。
- ADD #996,Rd:Rd 放到 \(A\)中,966 放到 \(Imm\) 中。
- SHL Rd:Rd 放到 \(A\)中。
运算类指令步骤三(EX
):进行运算,将结果存入 EX
段锁存器。
运算类指令步骤四(M
) :对于 RISC
系统,计算结果会直接放入寄存器,所以是空段,什么事情都不用做,但要消耗相应的时间。
运算类指令步骤五(WB
):运算结果写回指定寄存器。
12.2.LOAD 指令执行过程
LOAD 指令的功能是取数,会把主存或寄存器中的内容取至寄存器中,有如下两种描述方式:
LOAD Rd, 996(Rs) | (996+(Rs)) ->Rd |
LOAD Rd, mem | (mem)->Rd |
LOAD 指令步骤一(IF
):根据 PC 从指令 Cache
取指令到 IF 段的锁存器。
LOAD
指令步骤二(ID
):将基址寄存器的值放到锁存器 A A
A、将偏移量放到 \(Imm\)。
LOAD
指令步骤三(EX
):进行运算,得到有效地址。
LOAD 指令步骤四(M
) :从数据 Cache
中取数并放入锁存器。
LOAD
指令步骤五(WB
):将取出的数写回寄存器。
12.3.STORE 指令执行过程
STORE 指令的功能是存数,有如下两种描述方式:
STORE Rs, 996(Rd) | Rs->996+(Rd)) |
STORE Rs, mem | Rs->(mem) |
Store 指令步骤一(IF
):根据 PC 从指令 Cache
取指令到 IF 段的锁存器。
Store
指令步骤二(ID
):将基址寄存器的值放到锁存器 A A
A、将偏移量放到 \(Imm\)、将要存的数放到
\(B\)。
Store
指令步骤三(EX
):进行运算,得到有效地址,并将锁存器 \(B\) 的内容放到锁存器 Store。
Store 指令步骤四(M
) :写入数据
Cache。
Store 指令步骤五(WB
) :空段。
12.4.条件转移指令执行过程
如下:
- beq Rs,Rt, #偏移量:若 (Rs)==(Rt),则 (PC)+ 指令字长 +(偏移量 × 指令字长)->PC,否则有 (PC)+ 指令字长 ->PC。
- bne Rs,Rt, #偏移量:若 (Rs)!=(Rt),则 (PC)+ 指令字长 +(偏移量 × 指令字长)->PC,否则有 (PC)+ 指令字长 ->PC。
条件转移指令步骤一(IF
):根据 PC 从指令 Cache
取指令到 IF 段的锁存器。
条件转移指令步骤二(ID
):进行比较的两个数放入锁存器
\(A\)和 \(B\)、偏移量放入 \(Imm\)。
条件转移指令步骤三(EX
):进行运算,比较两个数。
条件转移指令步骤四(M
) :将目标 PC 值写回
PC。
条件转移指令步骤五(WB
)
:空段。
12.5.无条件转移指令执行过程
如下:
- jmp #偏移量:(PC)+ 指令字长 +(偏移量 × 指令字长)->PC。
无条件转移指令步骤一(IF
):根据 PC 从指令 Cache
取指令到 IF 段的锁存器。
无条件转移指令步骤二(ID
):偏移量放入 \(Imm\)。
无条件转移指令步骤三(EX
):将目标 PC 值写回
PC。
无条件转移指令步骤四(M
) :空段。
无条件转移指令步骤五(WB
) :空段。
13.多处理器基本概念
13.1.SISD、SIMD、MIMD 基本概念
计算机体系结构分类:基于指令流的数量和数据流的数量,可以将计算机体系结构分为如下 4 类:
- 单指令单数据流 SISD
- 单指令多数据流 SIMD
- 多指令单数据流 MISD
- 多指令多数据流 MIMD
13.1.1.单指令单数据流 SISD
单指令单数据流 SISD:常规的单处理器便是 SISD,其特性和硬件组成如下:
- 特性:①各指令序列只能并发而不能并行;②每条指令处理一两个数据;③不是数据级并行技术。
- 硬件组成:①一个处理器 + 一个主存储器;②若采用指令流水线,则需要设置多个功能部件,采用多模块交叉存储器。
《计算机组成原理》这门课程一直研究的便是 SISD。如下,此 CPU 在同一时间段内仅能处理一个进程或线程的一个指令序列,每条指令只能处理一两个数据。
13.1.2.单指令多数据流 SIMD
单指令多数据流 SIMD:其特性和硬件组成如下:
- 特性:①各指令序列只能并发而不能并行;②每条指令可以同时处理多个具有相同特征的数据;③是数据级并行技术。
- 硬件组成:①一个指令控制部件 + 多个处理单元 / 执行单元 + 一个主存储器;②每个执行单元有各自的寄存器组、局部存储器、地址寄存器;③不同执行单元执行同一条指令、处理不同的数据。
如下,在 SIMD 系统中,CU 每次会取出一条指令,根据此指令发出控制信号给各个执行部件(如 ALU),每个执行部件都有各自的寄存器(组)。
SIMD 系统善于对结构类似的大量数据做相同处理,例如:
- 图像处理时,对每个像素点作 “高斯模糊”。
- 可用于优化 for 循环中对数组元素的重复处理。
13.1.3.多指令单数据流 MISD
多指令单数据流 MISD:多条指令并行执行,处理同一个数据。现实中并不存在这种计算机。
13.1.4.多指令多数据流 MIMD
多指令多数据流 MIMD:常规的多处理器便是 MIMD,其特性如下:
- 各指令序列并行执行,分别处理多个不同的数据。
- 是一种线程级并行技术(甚至是线程级以上)。
MIMD 可以进一步分为:
- 多处理器系统
- 多计算机系统
13.1.4.1.多处理器系统
多处理器系统:是共享内存多处理器(SMP)的简称。其特性和硬件组成如下:
- 特性:各处理器之间,可以通过 LOAD/STORE 指令访问同一个主存储器,可以通过主存相互传送数据。
- 硬件组成:①一台计算机内,有多个处理器 + 一个主存储器;②多个处理器共享单一的物理地址空间。
13.1.4.2.多计算机系统
多计算机系统:其特性和硬件组成如下:
- 特性:各计算机之间,不可以通过 LOAD/STORE 指令直接访问对方的存储器,只能通过消息传递相互传送数据。
- 硬件组成:①由多台计算机组成,所以有多个处理器 + 多个主存储器;②每台计算机拥有各自的私有存储器,物理地址空间相互独立。
实际应用中,可以把单个任务拆分为多个任务,分别指派给不同的计算机执行。
13.2.向量处理器
向量处理机的LOAD指令,可以将一个向量取到向量寄存器中;加法指令,可以实现两个向量相加应用于:向量计算、大量浮点数计算,空气动力学、核物理学、巨型矩阵计算问题很多超级计算机如中国的“银河”就是向量处理器。
14.硬件多线程的基本概念
硬件多线程:在 (王道 408 考研操作系统) 第二章进程管理 - 线程概念和多线程模型这一节中我们说到了线程的一些缺点。线程粒度较进程来讲更细,而且线程切换包含很多开销,频繁切换线程必然会影响系统性能,所以为了减少开销便诞生了硬件多线程。在支持硬件多线程的 CPU 中,必须为每个线程提供单独的通用寄存器组、单独的程序计数器等,线程的切换只需激活选中的寄存器,从而省略了与存储器数据交换的环节,大大减少了线程切换的开销。共有如下 3 种实现方式
如下:
- 对于不支持硬件多线程的 CPU:同一时刻只能有一个线程运行,线程切换时需要保护现场,产生额外开销。
- 对于支持硬件多线程的 CPU:不同线程运行在不同环境中。
14.1.细粒度多线程
细粒度多线程:关键特征如下:
- 指令发射:轮流发射各线程的指令(每个时钟周期发射一个线程)。
- 线程切换频率:每个时钟周期切换一次线程。
- 线程切换代价:低。
- 并行性:指令级并行、线程间不并行。
14.2.粗粒度多线程
粗粒度多线程:关键特征如下:
- 指令发射:连续几个时钟周期,都发射同一线程的指令序列。流水线阻塞时,才切换另一个线程。
- 线程切换频率:只有流水线阻塞时才切换另一个线程。
- 线程切换代价:高(需要重载流水线)。
- 并行性:指令级并行、线程间不并行。
14.3.同时多线程
同时多线程:关键特征如下:
- 指令发射:一个时钟周期内同时发射多个线程的指令。
- 线程切换频率:NULL。
- 线程切换代价:NULL。
- 并行性:指令级并行、线程级并行。