时序信号 (timing signal)

第 3 版 · OCR 辅助 · 原书检索 · 文字用于定位,公式与图表请回原页核验 · 本次导入快照

### 时序信号 (timing signal)

时序信号指同步系统中用于进行同步控制的定时信号。早期计算机的处理器在设计时,采用机器周期一节拍一工作脉冲三级时序系统。现代计算机一般只用一个专门的时钟信号来进行定时。因此,现代计算机的时序信号就是时钟信号。

### 控制单元 (Control Unit, CU)

控制单元也称为控制部件、控制逻辑或控制器。其作用是对指令进行译码,将译码结果和状态/标志信号和时序信号等进行组合,产生各种操作控制信号。这些控制信号被送到 CPU 内部或通过总线送到主存或 I/O 模块。送到 CPU 内部的控制信号用于控制 CPU 内部数据通路的执行,送到主存或 I/O 模块的信号控制 CPU 和主存或者 CPU 和 I/O 模块之间的信息交换。控制单元是整个 CPU 的指挥控制中心,通过规定各部件在何时做什么动作来控制数据的流动,以完成指令的执行。


<!-- page: 122 -->

执行部件(Execute Unit, EU)

执行部件也称为操作部件或功能部件,由控制部件(CU)发来的操作控制信号进行控制,以完成特定的功能。有两种类型的执行部件,一种是用组合逻辑电路实现的“操作元件”,用于进行数据运算、数据传送等,如ALU、总线、扩展器和多路选择器等;另一种是用时序逻辑电路实现的“状态元件”,用于进行数据存储,如触发器、寄存器和存储器等。

组合逻辑电路(combinational logic circuit)

组合逻辑电路简称组合电路,用来构成操作元件。组合逻辑电路在逻辑功能上的特点是,任意时刻的输出仅仅取决于该时刻的输入,与电路原来的状态无关,因此,它没有存储功能。

时序逻辑电路(sequential logic circuit)

时序逻辑电路简称时序电路,用来构成状态元件。时序逻辑电路在逻辑功能上的特点是,任意时刻的输出不仅取决于当时的输入信号,而且还取决于电路原来的状态,或者说还与以前的输入有关。时序逻辑电路具有存储功能,能保存所存储的状态。

扩展器(extension unit)

扩展器是将一个 $n$ 位数扩展成更多位数或 $2n$ 位数的部件。一般有两种扩展方式:零扩展和符号扩展。

零扩展(0-extend)

零扩展即高位用0填充。例如,在MIPS指令系统中,一个16位的逻辑数需先进行零扩展,扩展为32位数后,在32位ALU中进行逻辑运算。零扩展可以看成对无符号数的扩展,扩展前后数值不变。

符号扩展(sign extend)

符号扩展即高位用扩展前的 $n$ 位数的符号位填充。例如,在MIPS指令系统中,Load/Store指令中的存储器地址偏移量需先进行符号扩展,将16位偏移量扩展为32位后,送到32位的ALU中,和基址进行加法运算。符号扩展可以看成对带符号整数扩展,扩展前后数值不变。

多路选择器(multiplexor)

多路选择器也称数据选择器或多路复用器。它根据控制线路的设置,选择多个输入信号中的一个进行输出。

定时方式(clocking methodology)

在时序电路中,定时方式规定了状态存储元件何时读出信号、何时写入信号。一般采用边沿触发的定时方式。

边沿触发(edge-triggered)

边沿触发规定存储元件中的状态只允许在时钟跳变边沿改变。时钟信号的跳变有正跳变和负跳变两种。在时钟的上升沿进行的跳变为正跳变;在时钟的下降沿进行的跳变为负跳变。

寄存器堆(register file)

寄存器堆就是寄存器集合,也称为通用寄存器组(GPRS)。其中的寄存器可以通过给定相应的寄存器编号来进行读写。在指令中用编号标识寄存器。执行指令时,指令中的寄存器编号被送到一个地址译码器进行译码选中某个寄存器进行写入,读出时寄存器编号作


<!-- page: 123 -->

为控制信号来控制一个多路选择器,选择相应的寄存器读出。实质上它是CPU中暂时存放数据的地方,里面保存着那些等待处理的数据或已经处理过的数据,CPU访问寄存器所用的时间要比访问内存的时间短。采用寄存器,可以减少CPU访问内存的次数,从而加快指令执行的速度。不过,因为受到芯片面积和集成度的限制,寄存器堆的容量不可能很大。

## 寄存器写信号(register write signal)

寄存器堆中的寄存器是由触发器构成的,而触发器的输出状态的变化只能发生在时钟边沿,因此,寄存器写控制信号在时钟边沿有效。时钟边沿到来时,事先稳定在输入端的数据开始向寄存器写入,经过一段时间延迟(这个延迟时间称为Click-to-Q)才能稳定地写入寄存器并输出,因此,时钟边沿到来时,在寄存器输出端的数据实际上还是上一个时钟周期内的老数据。

## 指令存储器(instruction memory)

指令存储器是专门存放指令的存储器,也称为代码存储器(code memory)。实际上,现代计算机中,CPU内的一级cache采用数据cache和代码cache分离的方式,因此,指令存储器实际上是CPU中的代码cache。

## 数据存储器(data memory)

数据存储器是专门存放数据的存储器。实际上,现代计算机中,CPU内的一级cache采用数据cache和代码cache分离的方式,因此,数据存储器实际上是处理器中的数据cache。

## 指令译码器(instruction decoder)

指令译码器是用来对指令的操作码进行译码的部件。在设计指令系统时,对每条功能不同的指令操作码进行了编码。因此,执行指令时,必须要有相应的译码电路对每个操作码进行译码解释。指令译码器的输入是指令操作码,输出结果用来和其他信号(如时序信号、机器状态信号、指令结果标志信号等)一起组合生成控制信号。不同的指令译码结果生成控制信号的不同取值,以控制执行部件完成不同的功能。

## 控制信号(control signal)

控制信号也称为操作控制信号或微操作信号。控制器中的指令译码器对指令进行译码,将译码结果和状态/标志信号、时序信号等进行组合,产生各种操作控制信号。这些控制信号被送到CPU内部或通过总线送到主存或I/O模块。送到CPU内部的控制信号用于控制CPU内部数据通路的执行,送到主存或I/O模块的信号控制CPU和主存或者CPU和I/O模块之间的信息交换。

## 时钟周期(clock cycle)

现代计算机的CPU采用时钟信号进行定时控制。若采用时钟边沿触发,则只有在时钟的上升沿或下降沿到来时才能把一个新的值写到一个状态单元中。所以,应该将所有相邻状态单元之间的组合逻辑电路中最长的延时作为时钟周期,以保证在一个时钟周期内所有的组合电路能完成必要的数据处理工作。

## 主频(CPU clock rate/frequency)

CPU的主频就是CPU时钟周期的倒数。

## 分支条件满足(branch taken)

对于条件跳转指令(即分支指令branch),其执行结果总有两种可能性(即两个分支或


<!-- page: 124 -->

两条执行路径);一种是条件满足(称为 branch taken),此时跳转到跳转目标地址处继续执行;另一种是条件不满足(称为 branch not taken),此时则继续取下条指令执行。

## 跳转目标地址(branch target address)

对于跳转指令(包括条件跳转指令、无条件跳转指令、调用指令等),其指令中给出的目标地址称为跳转目标地址。数据通路中必须要有相应的部件能够计算跳转目标地址,并根据情况选择将跳转目标地址送到PC中,作为下一条执行指令的地址。

## 硬布线控制器(hardwared control unit)

硬布线控制器是指采用组合逻辑电路和状态寄存器进行设计实现的控制器,也称为硬连线路控制器。在多周期数据通路中,一条指令的执行分多个阶段进行,每个阶段在一个时钟周期内完成,如果把每个阶段涉及的控制信号组合看成一个状态,则从一个阶段转移到下一个阶段就可以看作状态之间的转换,因此,所有指令的执行过程就可以用一个有限状态机来描述,控制器的功能就是实现这个有限状态机。因此,这种控制器设计方式也称为有限状态机方式,实现的控制器称为有限状态机控制器。它的优点是速度快,适合于实现简单或规整的指令系统。但是,因为它是一个多输入/多输出的巨大的逻辑网络,所以,对于复杂的指令系统来说,其结构庞杂,实现困难,修改、维护不易,灵活性差。

## 微程序控制器(microprogrammed control unit)

采用微程序设计方式实现的控制器称为微程序控制器。微程序设计的基本思想是,仿照程序设计的方法编制每个机器指令对应的微程序,每个微程序由若干微指令构成,每条微指令就是有限状态机中对应的一个状态,即若干控制信号的集合,所以每条微指令包含若干微命令,这些微命令实际上就是控制信号。所有指令对应的微指令序列都放在只读存储器中。当执行到某条指令时,取出对应的各条微指令,译码产生对应的微命令(即控制信号)并送到数据通路中相应的地方,控制其动作。这个只读存储器称为控制存储器(Control Storage,CS),简称控存。

## 微代码(microcode)

通常把事先存放在控制存储器(CS)中的微程序代码(即每个控存单元中的 0/1 序列)简称为微代码或微码。

## 微指令(microinstruction)

微指令和微代码的含义实际上是一样的,只是同一个概念从不同的角度来讲而已。控存中每个单元存放一条微指令,对应于有限状态机中的一个状态,每条微指令在一个时钟周期内完成。“微指令”与程序设计中“指令”的概念类似,也涉及格式和顺序控制等问题。

## 微程序(microprogram)

类似于程序设计中“程序”的概念,程序用于实现某个特定的算法功能,而微程序用于实现机器的指令;程序由若干指令构成,而微程序由若干条微指令构成;程序存放在内存中,而微程序存放在控制存储器中。

## 固件(firmware)

一般把写入 EPROM 等只读存储器中的程序称为固件,最初把固化在只读存储器的微程序称为固件,表示用软件实现的硬部件,现在对固件通俗的理解就是在 ROM 中“固化的软件”。固件是固化在集成电路内部的程序代码,负责控制和协调集成电路的功能。


<!-- page: 125 -->

## 中断过程 (interrupt processing)

中断过程是一个正常执行的程序被打断的过程,指在程序正常执行过程中,CPU遇到一些异常情况无法继续执行当前指令,或者外部设备发生一些特殊事件请求 CPU 处理。此时,CPU 中止原来正在执行的程序,转到处理异常情况或特殊事件的处理程序去执行,执行后再返回到原被中止的程序继续执行。中断过程的起因主要有来自处理器外部的“中断”和来自处理器内部的“异常”两种。

## 中断请求 (interrupt request)

中断请求是引起中断过程的原因之一。在程序执行过程中,若外设完成任务或发生某些特殊事件(如打印机缺纸、定时采样计数时间到、键盘缓冲满等),会向 CPU 发中断请求,要求 CPU 对这些情况进行处理。处理完后,回到原被中断的断点处继续执行。这种情况也被称为 I/O 中断(I/O interrupt)。特指由 CPU 外部的 I/O 设备向 CPU 发的中断请求。I/O 中断与执行的指令无关,是异步发生的外部事件,因此,也称为“外部中断”。

## 异常 (exception)

异常是引起中断过程的原因之一。在 CPU 执行某条指令时发生的一些特殊的非正常事件(如缺页、溢出、除数为 0、非法操作码等)都称为一种异常。异常是来自处理器内部的意外事件,是由正在执行的指令同步产生的特殊事件,也称为“内部异常”或“内中断”或“程序性中断”,它又可细分为故障、自陷、终止。

## 故障 (fault)

在执行某条指令时,可能发生一些特殊的“异常事件”,如缺页、溢出、除数为 0、非法操作码等,使当前指令无法继续执行。此时,CPU 只能中止原程序的执行,转到处理相应情况的程序去执行,处理完后,再回到发生异常的指令继续执行。这种情况被称为故障,是由正在执行的指令产生的。

## 自陷 (trap)

自陷是人为设定的事件,在程序中事先设定一条特殊的指令,通过执行这条特殊指令,自动中止正在执行的原程序,转到一个特定的内核管理程序去执行,执行完后,回到那条特殊指令后面的一条指令开始执行。自陷也称为自愿中断或陷阱。这些特殊的指令称为“访管指令”(访问管理程序)或“自陷指令”(自动掉入陷阱)或“陷阱指令”,如 x86 中的指令 INT n。

## 终止 (abort)

终止既不是外部设备发出的中断请求,也不是指令本身产生的异常情况或自愿中断,而是在执行指令过程中发生了硬件故障,如存储器校验故障等,使得指令无法继续执行。这类异常是随机发生的,对引起异常的指令的确切位置无法确定,出现这类严重错误时,原程序无法继续执行,只好终止,而由异常处理程序重新启动操作系统。

## 异常/中断处理程序 (exception/interrupt handler)

异常/中断处理程序是中断服务程序和异常处理程序的合称。当 CPU 发现外部中断或内部异常时,就会把当前正在执行的用户程序停下来,调出处理中断或异常的程序来执行,通常将进行中断处理的程序称为中断服务程序,进行异常处理的程序称为异常处理程序。异常/中断处理程序属于操作系统内核部分,发生中断或异常时,CPU 的状态要从用户态(即执行用户程序的状态,也称为目态)切换到管理态(即执行操作系统管理程序,也称为


<!-- page: 126 -->

管态、内核态或核心态)。

## 异常程序计数器(Exception PC、EPC)

异常程序计数器是 MIPS 处理器中用于保存出错指令或中断返回后所执行指令的地址的寄存器。它的位数和 PC 的位数一样。通常把这个被保存的地址称为断点,把这个地址送到 EPC 的过程称为保存断点。

## 原因寄存器(cause register)

原因寄存器用于记录异常或中断类型的状态寄存器。每一位的含义应事先规定,例如,第 1 位为 1 则表示出现了“溢出”异常,第二位为 1 则表示出现了“非法指令”,第三位为 1 则是“缺页”,等等。在外部接口(如中断控制器)中也有类似的状态寄存器,用以记录中断请求的类型,一般称为中断请求寄存器。

## 中断允许触发器(interrupt enable register)

中断允许触发器是在 CPU 中用来设置中断允许/中断禁止状态的触发器。关中断时,中断允许触发器被设置为 0,表示不允许响应中断。开中断时,中断允许触发器被设置为 1,表示允许响应中断。

## 关中断(interrupt OFF)

关中断是将中断允许触发器设置为 0 的操作,表示不允许响应中断。

## 开中断(interrupt ON)

开中断是将中断允许触发器设置为 1 的操作,表示允许响应中断。

## 5.4 常见问题解答

1. 从事 CPU 设计的人会很少,为什么大家都要学习如何设计 CPU 呢?

答:首先,从智力方面来说,处理器设计是有趣而富有挑战性的。“现代微处理器可以称得上是人类创造出的最复杂的系统之一”,“处理器要完成复杂的任务,但又要求结构尽可能简单”;其次,理解处理器如何工作能够帮助理解整个计算机系统是如何工作的。第三,虽然没有很多人设计处理器,但会有很多人从事嵌入式系统的设计。现代许多机电产品中都有处理器芯片嵌入其中,嵌入式系统的设计者必须了解处理器是如何工作的,因为这些系统通常在较低的抽象层次上进行编程设计。第四,你将来的工作可能就是设计处理器。(引自 [美] Randal E. Bryant &amp; David O'Hallaron *Computer Systems A Programmer's Perspective* 中的第 4 章)

现代计算机的处理器基本上都采用流水线方式执行指令,流水线方式的数据通路比较复杂,所以先从简单的单周期数据通路和多周期数据通路开始理解,就是本章的内容。有了这些基础,对流水线处理器理解起来就较容易了。深刻理解流水线方式处理器的工作原理对于如何设计高质量的程序、如何进行编译优化、如何设计高性能计算机系统等都是非常必要的。

2. 一条指令的执行过程中要做哪些事情呢?

答:一条指令的执行过程包括取指令、指令译码、计算操作数地址、取操作数、运算、送结果。其中取指令和指令译码是每条指令都必须进行的操作。有些指令需要到存储单元取操作数,因此,需要在取数之前计算操作数所在的存储单元地址。取操作数和送结果这两个


<!-- page: 127 -->

步骤,对于不同的指令其取和送的地方可能不同,有些指令要求在寄存器读取/保存数据,有些是在内存单元中读取/保存数据,还有些是对 I/O 端口进行读取或保存数据。因此,一条指令的执行阶段(不包括取指令阶段),既可能只有 CPU 参与,也可能要通过总线去访问主存,还可能要通过总线去访问 I/O 端口。

## 3. CPU 总是在执行指令吗?会不会停下来什么都不做?

答:CPU 的功能就是不断地周而复始地执行指令,而每条指令又都有不同的步骤,每个步骤在一定的时间内完成。因此,CPU 总是在不停地执行指令。有时我们会说,CPU 停止或 CPU 正在等待,什么事情也不做。事实上,CPU 还是在执行指令,只不过可能处于以下几种情况之一:① CPU 正在执行某条指令的过程中,发生了诸如 cache 缺失这样需要访问内存或 I/O 端口的事件,此时当前正在执行的指令无法继续执行到下一步,因此,CPU 就处于等待(阻塞)状态,直到主存或 I/O 完成读写操作;② CPU 正在不断地通过执行指令以查询外设是否就绪,在查询过程中,CPU 什么实质性的工作都没有做;③ CPU 正在执行一连串的空指令(NOP),什么实质性工作都没有做。综上所述,CPU 不可能不在执行指令,只是指令的执行过程被阻塞了一段时间或执行了没有产生结果的指令。

## 4. CPU 除了执行指令外,还做什么事情?

答:CPU 的工作过程就是周而复始地执行指令,计算机各部分所进行的工作都是由 CPU 根据指令的要求来启动的。为了使 CPU 和外部设备能够很好地协调工作,尽量使 CPU 不等待甚至不参与外部设备的输入和输出过程,CPU 对外设的输入、输出控制采用了程序中断方式和 DMA 方式。这两种方式下,外部设备需要向 CPU 提出中断请求或 DMA 请求,因此,在执行指令过程中,CPU 还要定时通过采样相应的引脚来查询有没有中断请求或 DMA 请求。如果有中断请求,那么 CPU 要进行一系列操作来完成从正在执行的用户程序到中断处理程序的切换;如果有 DMA 请求,那么还要给出响应 DMA 请求的一些控制信号。另外,CPU 在一条指令的执行过程中,还可能发生一些异常事件,因此,也需要 CPU 能通过相应的动作,转换到异常事件处理程序去执行。不过,查询或响应中断请求和 DMA 请求的过程都是包含在一条指令执行过程中的。

## 5. 对于 CPU 中的所有寄存器,用户都能访问吗?

答:CPU 中的寄存器分为用户可访问寄存器和用户不可见寄存器。一般把用户可访问寄存器称为通用寄存器(GPR)。这些寄存器都有一个编号,在指令中用编号标识寄存器。因此执行指令时,指令中的寄存器编号要送到一个地址译码器进行译码,然后才能选中某个寄存器进行读写。通用寄存器可以用来存放操作数或运算结果,或者作为地址指针、变址寄存器、基址寄存器等。

CPU 中有一些寄存器是用户不可见的,没有编号、不能通过程序直接访问。例如,指令寄存器(IR)、程序状态字寄存器(PSWR)、存储器地址寄存器(MAR)、存储器数据寄存器(MDR)等。

对于程序计数器(PC),它虽然是专用寄存器,没有编号,不能在指令中被明确指定,但用户可以通过跳转类指令来修改其值,以改变程序执行的顺序。

## 6. CPU 执行指令的过程中,其他部件在做什么?

答:计算机的工作过程就是连续执行指令的过程,整个计算机各个部分的动作都是由 CPU 中的控制部件(CU)通过对指令译码送出的控制信号来控制的。其他部件不知道自己


<!-- page: 128 -->

该做什么,该完成什么动作,只有 CPU 通过对指令译码才知道。如果指令中包含有对存储器或 I/O 端口的访问,则必须由 CPU 通过总线,把要访问的地址和操作命令(读还是写)等信息送到存储器或 I/O 接口来启动相应的读或写操作。例如,若不采用 cache,则每次指令执行前,都要通过向总线发出主存地址、主存读命令等来控制存储器取指令;若当前执行的是寄存器定点加法指令,则 CU 控制定点运算器进行动作;若是 I/O 指令,则 CU 会通过总线发出 I/O 端口地址、I/O 读或 I/O 写命令等来控制对某个 I/O 接口中的寄存器进行读写操作。所以说,CPU 在执行指令时,其他部件也可能在执行同样的指令,只不过它们各司其职:CU 负责解释指令和发出命令(控制信号),而各个部件则按命令具体完成自己该完成的任务(如读写、运算等)。

## 7. 怎样保证 CPU 能按程序规定的顺序执行指令呢?

答:计算机的工作过程就是连续执行指令的过程,指令在主存中连续存放。一般情况下,指令被顺序执行,只有遇到跳转指令(如无条件跳转、条件分支、调用和返回等指令)才改变指令执行的顺序。当执行到非跳转指令时,CPU 中的指令译码器通过对指令译码,知道正在执行的是一种顺序执行的指令,所以就直接通过对 PC 加“1”(这里的“1”是指一条指令的长度)来使 PC 指向下一条顺序执行的指令;当执行到跳转指令时,指令译码器知道正在执行的是一种跳转指令,因而,控制运算器根据指令执行的结果进行相应的地址运算,把运算得到的跳转目标地址送到 PC 中,使得执行的下一条指令为跳转到的目标指令。

由此可以看出,指令在主存中的存放顺序是静态的,而指令的执行顺序是动态的。CPU 能根据指令执行的结果动态改变程序的执行流程。