失眠网,内容丰富有趣,生活中的好帮手!
失眠网 > 《深入理解计算机系统》学习笔记——处理器体系结构

《深入理解计算机系统》学习笔记——处理器体系结构

时间:2018-08-13 04:46:44

相关推荐

《深入理解计算机系统》学习笔记——处理器体系结构

计算机系统——处理器体系结构

Y86-64指令集体系结构程序员可见的状态Y86-64指令指令编码Y86-64异常Y86-64程序一些Y86-64指令的详情逻辑设计和硬件控制语言HCL逻辑门组合电路和HCL布尔表达式字级的组合电路和HCL整数表达式集合关系存储器和时钟Y86-64的顺序实现将处理组织成阶段SEQ硬件结构SEQ的时序SEQ阶段的实现流水线的通用原理计算流水线流水线操作的详细说明流水线的局限性带反馈的流水线系统Y86-64的流水线实现SEQ+: 重新安排计算阶段插入流水线寄存器对信号进行重新排列和标号

Y86-64指令集体系结构

定义一个指令集体系结构(例如 Y86-64 ) 包括定义各种状态单元、指令集和它们的编码、一组编程规范和异常事件处理。

程序员可见的状态

Y86-64 程序中的每条指令都会读取或修改处理器状态的某些部分。这称为程序员可见状态,这里的"程序员”既可以是用汇编代码写程序的人,也可以是产生机器级代码的编译器。

- 有15个程序寄存器:%rax、%rcx、%rdx、%rbx、%rsp、%rbp、%rsi、%rdi 和 %8 到 %14。每个程序寄存器存储一个64位的字。- 寄存器%rsp 被入栈、出栈、调用和返回指令作为栈指针。寄存器没有固定的含义或固定值。- 有3个一位的条件码:ZF、SF 和 OF,它们保存着最近的算术或逻辑指令所造成影响的有关信息。- 程序计数器(PC)存放当前正在执行指令的地址。- 内存从概念上来说就是一个很大的字节数组,保存着程序和数据。Y86-64 程序用虚拟地址来引用内存位置。硬件和操作系统软件联合起来将虚拟地址翻译成实际或物理地址,指明数据实际存在内存中哪个地方。- 程序状态的最后一个部分是状态码 Stat,它表明程序执行的总体状态。会指示是正常运行,还是出现了某种异常。

Y86-64指令

Y86-64 ISA中各个指令的简单描述

这个指令集就是我们处理器实现的目标。 Y86-64 指令集基本上是 x86-64 指令集的一个子集。它只包括 8 字节整数操作,寻址方式较少, 操作也较少。因为我们只有 8 字节数据, 所以称之为 ” 字( word ) " 不会有任何歧义。

指令编码

15 个程序寄存器中每个都有一 个相对应的范围在 0 到 0xE 之间的寄存器标识符 ( register ID )。

程序寄存器存在CPU 中的一个寄存器文件中,这个寄存器文件就是一个小的、以寄存器 ID 作为地址的随机访问存储器。

指令集的一个重要性质就是字节编码必须有唯一的解释。任意一个字节序列要么是一个唯一的指令序列的编码, 要么就不是一个合法的字节序列。

Y86-64异常

对于 Y86-64 , 当遇到这些异常的时候,我们就简单地让处理器停止执行指令。

在更完整的设计中,处理器通常会调用一个异常处理程序(exception handler), 这个过程被指定用来处理遇到的某种类型的异常。

Y86-64程序

指令集模拟器 YIS , 它的目的是模拟 Y86-64 机器代码程序的执行,而不用试图去模拟任何具体处理器实现的行为。这种形式的模拟有助于在有实际硬件可用之前调试程序 ,也有助于检查模拟硬件或者在硬件上运行程序的结果 。

一些Y86-64指令的详情

大多数Y86-64 指令是以一种直接明了的方式修改程序状态的,所以定义每条指令想要达到的结果并不困难。不过,两个特别的指令的组合需要特别注意一下。

pushq 指令会把栈指针减8 , 并且将一个寄存器值写入内存中。因此,当执行 pushq %rsp 指令时,处理器的行为是不确定的,因为要入栈的寄存器会被同一条指令修改。

通常有两种不同的约定: 1 ) 压入 %rsp 的原始值, 2 ) 压入减去 8 的%rsp 的值 。

逻辑设计和硬件控制语言HCL

逻辑 1 是用1.0 伏特左右的高电压表示的, 而逻辑 0 是用 0.0伏特左右的低电压表示的。

要实现一个数字系统需要三个主要的组成部分:

计算对位进行操作的函数的组合逻辑、存储位的存储器单元,以及控制存储器单元更新的时钟信号。

逻辑门

逻辑门是数字电路的基本计算单元。它们产生的输出,等于它们输入位值的某个布尔函数。

在 HCL 中我们还是把它们写作二元运算符, 所以, 三个输入的 AND 门, 输入为 a、b 和 c , 用 HCL 表示就是 a &&b &&c 。

逻辑门总是活动的 ( active )。

一旦一个门的输入变化了,在很短的时间内,输出就会相应地变化。

组合电路和HCL布尔表达式

将很多的逻辑门组合成一个网,就能构建计算块( com putational block), 称为组合电路(combinational circuits )。

构建的限制:

- 每个逻辑门的输入必须连接到下述选项之一:1) 一个系统输入(称为主输入), 2) 某个存储器单元的 输出,3) 某个逻辑门的输出。- 两个或多个逻辑门的输出不能连接在一起。否则它们可能会使线上的 信号矛盾,可能会导致一个不合法的电压或电路故障。- 这个网必须是无环的。也就是在网中不能有路径经过一系列的门而形成一个回路, 这样的回路会导致该网络计算的函数有歧义。

字级的组合电路和HCL整数表达式

通过将逻辑门组合成大的网,可以构造出能计算更加复杂函数的组合电路。通常,我们设计能对数据字( word ) 进行操作的电路。

有一些位级信号,代表一个整数或一些控制模式。

在 HCL 中, 我们将所有字级的信号都声明为 int , 不指定字的大小。这样做是为了简单。

在全功能的硬件描述语言中, 每个字都可以声明为有特定的位数。

在 HCL 中,多路复用函数是用情况表达式 ( case expression ) 来描述的。

情况表达式的通用格式如下:

组合逻辑电路可以设计成在字级数据上执行许多不同类型的操作。

算术/逻辑单元 ( ALU ) 是一种很重要的组合电路, 下图是它的一个抽象的图示 。

集合关系

判断集合关系的通用格式是:

这里被测试的值 iexpr 和待匹配的值 iexpr1iexpr_1iexpr1​ ~ iexprkiexpr_kiexprk​ 都是整数表达式。

存储器和时钟

组合电路从本质上讲,不存储任何信息。相反,它们只是简单地响应输入信号,产生等于输入的某个函数的输出。

为了产生时序电路 ( sequential circuit ) , 也就是有状态并且在这个状态上进行计算的系统,我们必须引入按位存储信息的设备。

存储设备都是由同一个时钟控制的,时钟是一个周期性信号,决定什么时候要把新值加载到设备中。

两种存储器设备:

- 时钟寄存器(简称寄存器)存储单个位或字。时钟信号控制寄存器加载输入值。- 随机访问存储器(简称内存)存储多个字,用地址来选择该读或该写哪个字。

Y86-64处理器会用时钟寄存器保存程序计数器(PC)、条件代码(CC)和程序状态(Stat)。

我们的处理器还包括另外一个只读存储器,用来读指令。

在大多数实际系统中,这两个存储器被合并为一个具有双端口的存储器:一个用来读指令,另一个用来读或者写数据。

Y86-64的顺序实现

将处理组织成阶段

处理一条指令包含很多操作,将它们组织成某个特殊的阶段序列。

分为以下几个阶段:

取指:取指阶段从存储器读取指令字节,地址为程序计数器(PC)的值。译码:译码阶段从寄存器文件读入最多两个操作数,得到valA 和 / 或 valB。执行:执行阶段,算术/逻辑单元要么执行指令明确的操作(根据ifun的值),计算存储器引用的有效地址,要么增加或减少栈指针。得到的值为valE。访存:访存阶段可将数据写入存储器或从存储器读出数据。写回:最多可写两个结果到寄存器文件。更新PC:将PC设置成下一指令的地址。

整数操作指令的处理遵循上面列出的通用模式。

在取指阶段,我们不需要常数字,所以 valP 就计算为 PC+2。

在译码阶段,我们要读两个操作数。

在执行阶段,它们和功能指示符 ifun一起再提供给 ALU , 这样一来 valE 就成为了指令结果。

SEQ硬件结构

SEQ 的抽象视图,一种顺序实现。

指令执行过程中的信息处理沿着顺时针方向的流程进行 ,从用程序计数器 ( PC ) 取指令 开始, 如图中左下角所示

硬件单元与各个处理阶段相关联:

取指:将程序计数器寄存器作为地址,指令内存读取指令的字节 。PC 增加器(PC incre­menter)计算 valP, 即增加了的程序计数器。

译码:寄存器文件有两个读端口 A 和 B,从这两个端口同时读寄存器值valA 和 valB 。

执行:执行阶段会根据指令的类型,将算术/逻辑单元( ALU ) 用于不同的目的。对整数操作 , 它要执行指令所指定的运算 。

访存:在执行访存操作时,数据内存读出或写入一个内存字。指令和数据内存访问的是相同的内存位置,但是用于不同的目的。

PC 更新 :程序计数器的新值选择自: valP, 下一条指令的地址; valC, 调用指令或跳转指令指定的目标地址; valM, 从内存读取的返回地址。

SEQ的时序

SEQ 的实现包括组合逻辑和两种存储器设备:时钟寄存器(程序计数器和条件码寄存器),随机访问存储器(寄存器文件、指令内存和数据内存)。

组合逻辑不需要任何时序或控制——只要输入变化了,值就通过逻辑门网络传播。

遵循以下原则组织计算:

原则:从不回读

处理器从来不需要为了完成一条指令的执行而去读由该指令更新了的状态。

用时钟来控制状态单元的更新,以及值通过组合逻辑来传播,足够控制我们SEQ实现中每条指令执行 的计算了。每次时钟由低变高时,处理器开始执行一条新指令。

SEQ阶段的实现

nop指令只是简单地经过各个阶段,除了要将PC加 1 , 不进行任何处理。halt 指令使得处理器状态被设置为 HLT , 导致处理器停止运行。

1.取指阶段

2. 译码和写回阶段

3. 执行阶段

4.访问阶段

5.更新PC阶段

SEQ小结

通过将执行每条不同指令所需的步骤组织成一个统一的流程,就可以用很少量的各种硬件单元以及一个时钟来控制计算的顺序, 从而实现整个处理器。

SEQ 唯一的问题就是它太慢了。

引入流水线能获得更好的性能。

流水线的通用原理

流水线化的一个重要特性就是提高了系统的吞吐量( throughput ) , 也就是单位时间内服务的顾客总数, 不过它也会轻微地增加延迟 (latency ) , 也就是服务一个用户所需要的时间。

计算流水线

在现代逻辑设计中,电路延迟以微微秒或皮秒( picosecond , 简写成 " ps " ), 也就是10-12 秒为单位来计算 。

我们以每秒千兆条指令( GIPS ) , 也就是每秒十亿条指令,为单位来描述吞吐量。从头到尾执行一条指令所需要的时间称为延迟( latency ) 。在此系统 中, 延迟为 320 ps , 也就是吞吐量的倒数。

在各个阶段之间放 上流水线寄存 器( pipeline register) , 这样每条指令都会按照三步经过这个系统, 从头到尾需要三个完整的时钟周期。

在这个系统中,我们将时钟周期设为 100 + 20 = 120ps , 得到的吞吐量大约为 8. 33 GIPS 。因为处理一条指令需要 3 个时钟周期 ,所以这条流水线的延迟就是 3 X 120 = 360ps 。我们将系统吞吐最提高到原来的 8. 33/ 3. 12 = 2. 67 倍, 代价是增加了一些硬件, 以及延迟的少量增加( 360 / 320 = 1. 12 ) 。

延迟变大是由于增加的 流水线寄存器的时间开销。

流水线操作的详细说明

流水线的局限性

可以将计算分成三个相互独立的阶段,每个阶段需要的时间是原来逻辑需要时间的三分之一。不幸的是,会出现其他一些因素,降低流水线的效率。

流水线操作的一个时钟周期。在时刻 240( 点 1 ) 时钟上升之前,指令 11 和 12 已经完成了阶段

B 和 A。在时钟上升后,这些指令开始传送到阶段 C 和 B, 而指令13 开始经过阶段 A( 点 2

和 3 ) 。就在时钟开始再次上升之前, 这些指令的结果就会传到 流水线寄存器的输入(点4 )

1.不一致的划分

对硬件设计者来说,将系统计算设计划分成一组具有相同延迟的阶段是一个严峻的挑战。通常,处理 器中的某些硬件单元,如 ALU 和内存,是不能被划分成多个延迟较小的单元的。这就使得创建一组平衡的阶段非常困难。在设计流水线化的 Y86-64 处理器中 ,我们不会过于关注这一层次的细节,但是理解时序优化在实际系统设计中的重要性还是非常重要的。

2.流水线过深,收益反而下降

为了提高时钟频率,现代处理器采用了很深的 (1 5 或更多的阶段)流水线。处理器架构师将指令的执行划分成很多非常简单的步骤 , 这样一来每个阶段的延迟就很小 。

电路设计者小心地设计流水线寄存器,使其延迟尽可能得小。

芯片设计者也必须小心地设计时钟传播网络,以保证时钟在整个芯片上同时改变。所有这些都是设计高速微处理器面临的挑战。

带反馈的流水线系统

对于像 x86-64 或 Y86-64 这样执行机器程序的系统来说,相邻指令之间很可能是相关的。

在这个包含三条 指令的序列中,每对相邻的指令之间都有数据相关( dat a dependen­cy),用带圈的寄存器名字和它们之间的箭头来表示。irmovq 指令(第1行)将它的结果存放在 %rax 中,然后 addq 指令(第2行)要读这个值 ;而 addq 指令将它的结果存放在%rbx 中, mrmovq 指令(第3 行)要读这个值。

另一种相关是由于指令控制流造成的顺序相关 。

Y86-64的流水线实现

SEQ+: 重新安排计算阶段

只需要对整体硬件结构做最小的改动,对于流水线阶段中的活动的时序,它能工作得更好。我们称这种修改过的设计为 " SEQ+ " 。

SEQ 到 SEQ + 中对状态单元的改变是一种很通用的改进的例子, 这种改进称为电路重定时 ( circuit retiming) [68]。

重定时改变了一个系统的状态表示, 但是并不改变它的逻辑行为 。通常用它来平衡一个流水线系统中各个阶段之间的延迟 。

插入流水线寄存器

流水线寄存器按如下方式标号:

F保存程序计数器的预测值。

D位于取指和译码阶段之间 。它保存关于最新取出的指令的信息,即将由译码阶段进行处理。

E位于译码和执行阶段之间。它保存关于最新译码的指令和从寄存器文件 读出的值的信息,即将由执行阶段进行处理。

M位于执行和访存阶段之间。它保存最新执行的指令的结果, 即将由访存阶段进行处理。它还保存关于用于处理条件转移的分支条件和分支目标的信息。

W位千访存阶段和反馈路径之间, 反馈路径将计算出来的值提供给寄存器文件写, 而当完成ret 指令时,它还要向 PC 选择逻辑提供返回地址。

对信号进行重新排列和标号

顺序实现 SEQ 和 SEQ+ 在一个时刻只处理一条指令, 因此诸如 valC、 srcA 和 valE 这样的信号值有唯一的值。在流水线化的设计中,与各个指令相关联的这些值有多个版本,会随着指令一起流过系统。

SEQ十和 PIPE— 的译码阶段都产生信号 dstE 和 dstM, 它们指明值valE 和 valM 的目的寄存器。

学习参考资料:

《深入理解计算机系统》 第3版

如果觉得《《深入理解计算机系统》学习笔记——处理器体系结构》对你有帮助,请点赞、收藏,并留下你的观点哦!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。