第六周(10.12-10.18):
学习计时:共10小时 读书:5 代码:1 作业:3 博客:1 |
一、学习目标 |
1. 了解ISA抽象的作用 2. 掌握ISA,并能举一反三学习其他体系结构 3. 了解流水线和实现方式 |
二、学习资源 |
1. 教材:第四章《处理器体系结构》,详细学习指导见这:重点是4.1-4.3 2. 课程资料:https://www.shiyanlou.com/courses/413 实验五,课程邀请码:W7FQKW4Y 3. 教材中代码运行、思考一下,读代码的学习方法见这。 |
三、学习方法 |
1. 进度很重要:必须跟上每周的进度,阅读,练习,问答,项目。我会认真对待每一位同学,请你不要因为困难半途而废。 2. 问答很重要:遇到知识难点请多多提问,这是你的权利更是您对自己负责的义务。问答到博客园讨论小组:http://group.cnblogs.com/103791/ 3. 实践很重要:解决书中习题,实践书中实例,完成每周项目,才算真的消化了这本好书。通过实验楼环境或自己安装的虚拟机在实践中进行学习 4. 实验报告很重要:详细记录你完成项目任务的思路,获得老师点评和帮助自己复习。学习完成后在博客园中(http://www.cnblogs.com/)把学习过程通过博客发表,博客标题"信息安全系统设计基础第六周学习总结" |
四、学习任务 |
(提示:请将要求学生完成的任务、测验或思考题列在此处)
1. 阅读教材,完成课后练习(书中有参考答案) 4.1-4.3中练习,重点:4.1 4.2 4.5 4.6 4.8 4.10 4.11 4.12 4.16 4.17 4.19 4.21 4.24 2. 考核:练习题把数据变换一下 3. 实验:需要动手的到实验楼中练习一下
|
五、后续学习预告(可选): |
第六章《存储器层次结构》 |
六、学习过程 |
(提示:此处由学生填写,学习过程,学习笔记,代码编译,运行结果,思考等) |
七、遇到的问题及解决 |
(提示:此处由学生填写,是重要的得分点,要写出遇到的问题和解决方案以及对出现问题的思考) |
八、其他 |
(提示:此处由学生填写,灵感,领悟等) |
第六周:学习任务教材 第四章
本章内容是处理器体系结构,重点掌握ISA,并能举一反三;本章带着大家设计并实现了一个结合CISC和RISC思想的处理器Y86,一个类IA32体系的处理器;ISA在编译器编写者和处理器设计者之间提供了一个抽象。
本章重点是4.1-4.3,流水线部分4.4-4.5供学有余力的同学自学
练习题:4.1 4.2 4.5 4.6 4.8 4.10 4.11 4.12 4.16 4.17 4.19 4.21 4.24
第四章
处理器体系结构
一个处理器支持的指令和指令的字节级编码称为它的指令集体系结构ISA。
4.1 Y86指令集体系结构
4.1.1程序员可见状态
Y86程序中的每条指令都会读取或者修改处理器状态的某些部分这称为程序员可见状态。这里的"程序员"既可以是用汇编代码写程序的人,也可以是产生机器级代码的编译器。在处理器实现中,只要我们保证机器级程序能够访问程序员可见状态,就不需要完全按照ISA隐含的方式来表示和组织从这个处理器状态。Y86有8个程序寄存器:%eax、%ecx、%edx、%ebx、%esi、%edi、%esp、%ebp。
有3个一位的调价吗:ZF、SF、OF,它们保存最近的算术或逻辑指令所造成影响的有关信息。
程序员可见状态:
存储器,从概念上说就是一个很大的字节数组,保存着程序和数据。Y86程序用虚拟地址来引用存储器位置。硬件和操作系统软件联合起来将虚拟地址翻译成实际或物理地址,指明数据实际保存在存储器中哪个地方。
程序状态的最后一个部分是状态码Stat,表明程序执行的总体状态。
4.1.2 Y86指令
Y86指令集:
·IA3的movl指令分成了4个不同的指令:irmovl、rrmovl、mrmovl、rmmovl,分别显式地指明源和目的格式,可以是立即数、寄存器或寄存器。指令名字的第一个字母就表明了源的类型,目的可以是寄存器或存储器。指令名字的第二个字母指明了目的类型,在决定如何实现数据传送时,显式地指明数据传送的这4种类型很有帮助。
两个存储器传送指令中的存储器引用方式是简单的基址和偏移量形式。不支持第二变址寄存器和任何寄存器值的伸缩。
同IA32一样,不允许从一个存储器地址直接传送到另一个存储器地址。也不允许将立即数传送到存储器。
·有4个整数操作指令
·7个跳转指令
·6个条件传送指令:cmovle、cmovl、cmove、cmovne、cmovge、cmovg
·call指令将返回地址入栈,然后跳到目的地址。Ret指令从这样的过程调用中返回。
·pushl和popl指令实现了入栈和出栈
·halt指令停止指令的执行。
4.1.3指令编码
Rrmovl与条件传送有同样的指令代码。可以把它看做是一个"无条件传送",就好像jmp指令是无条件跳转一样,它们的功能代码都是0。
Y86指令集的功能码:
8个程序寄存器中每个都有相应的0~7的寄存器标识符。
程序寄存器存在CPU的一个寄存器文件中,这个寄存器文件就是一个小的、以寄存器ID作为地址的随机访问存储器。在指令编码中以及在我们的设计中,当需要指明不应访问任何寄存器是,就用ID值0xF表示。
可能有附加的寄存器指示符字节制定一个或两个寄存器。根据指令类型,指令可以指定用于数据源和目的的寄存器,或是用于地址计算的基址寄存器。没有寄存器操作数的指令,就没有寄存器指示符字节。那些只需要一个寄存器操作数得指令将另一个寄存器指示符设为0xF。
有些指令需要一个附加的4字节常数字。这个字能作为irmovl的立即数数据,rmmovl和mrmovl的地址指示符的偏移量,以及分支指令和调用指令的目的地址。分支指令和调用指令的目的地只是一个绝对地址,而不是像IA32中那样使用PC相对寻址方式。所有整数采用小端法编码,当指令按照反汇编格式书写时,这些字节就以相反的顺序出现。
指令集的一个重要性质就是字节编码必须有唯一的解释。每条指令的第一个字街有唯一的代码和功能组合,给定这个字节,我们就可以决定所有其他附加字节的长度和含义。这个性质保证了处理器可以无二地执行目标代码程序。
CISC和早期的RISC:
、
4.1.4 Y86异常
程序员可见的状态包括stat状态码,他描述程序执行的总体状态。Y86状态码:
处理器通常会调用一个异常处理程序,被指定用来处理遇到的某种类型的异常,异常处理程序可以被配置成不同的结果,放弃程序或者调用一个用户自定义的信号处理程序。
Y86没有伸缩寻址模式。
以"."开头的词是汇编器命令,它们告诉汇编器调整地址,以便在那儿产生代码或插入一些数据。创建Y86代码的唯一工具是汇编器,程序员必须执行本来通常交给编译器、链接器和运行时系统同来完成的任务。
指令集模拟器称为YIS,模拟Y86机器代码程序的执行,不用试图去模拟任何及具体处理其实现的行为。有助于在有实际硬件可用之前调试程序,也有助于检查模拟硬件或者在硬件上运行程序的结果。
4.1.6一些Y86指令的详情
大多数Y86指令是以一种直接的方式修改程序状态的,所以定义每条指令想要达到的结果并不困难。
Pushl指令会把栈指针减去4,并且将一个寄存器值写入存储器中,执行pushl%esp时,处理器的行为是不确定的,因为要入栈的寄存器会被同一条指令修改,通常有两种约定:1.压入%esp的原始值,2.压入减去4的%esp值。
当执行压入栈指针寄存器指令时,不同的型号的x86处理器会做不同的事情,有些会压入原始的值,而有些会压入减去后的值。2个缺点:
·它降低了代码的可移植性
·它增加了文档的复杂性
要实现一个数字系统需要三个主要的组成部分:计算对位进行操作的函数的组合逻辑,存储位的存储器元素以及控制存储器元素更新的时钟信号。
4.2逻辑设计和硬件控制语言HCL
4.2.1逻辑门
逻辑门是数字电路的基本计算元素。产生的输出等于它们输入位值的某个布尔函数。逻辑门总是活动的,一旦一个门的输入变化了,在很短的时间内,输出就会相应地变化。
逻辑门类型:
4.2.2组合电路和HCL布尔表达式
将很多的逻辑门组合成一个网,救恩给你构建计算块,称为组合电路。两条限制:
两个或多个逻辑门的输出不能连在一起
这个网必须是无环的
4.2.3字级的组合电路和HCL整数表达式
将逻辑门组合成大的网,可以构造出能计算更加复杂函数的组合电路。
执行字级计算的组合电路根据输入字的各个位,用逻辑门来计算输出字的各个位。
处理器中会用到很多种多路复用器。在HCL中,多路复用函数使用情况表达式来描述的。
逻辑上讲,这些选择表达式是顺序求值的,且第一个求值为1的情况下会被选中。
允许不互斥的选择表达式使得HCL代码的可读性更好。
选择表达式可以是任意的布尔表达式,可以有任意多的情况,这就使得情况表达式能描述带复杂选择标准的、多种输入信号的块。
组合逻辑电路可以设计成在字级数据上执行许多不同类型的操作。算数/逻辑单元(ALU)是一种很重要的组合电路。
算数/逻辑单元(ALU):
4.2.4集合关系
在处理器设计中,很多时候都需要将一个信号与许多可能匹配的信号做比较,以此来检测真该处理的某个指令代码是否属于某一类指令代码。
4.2.5存储器和时钟
组合电路从本质上讲不存储任何信息。只是简单地相应输入信号,产生等于输入的某个函数的输出。存储设备都是由同一个时钟控制,始终是一个周期性信号,决定什么时候要把新值加载到设备中。两类存储器设备:
·时钟存储器(简称寄存器)存储单个位或字。时钟信号控制寄存器加载输入值。
·随机访问存储器(简称存储器)存储多个字,用地址来选择该读或者该写那个字。
硬件和机器级编程时,"寄存器"这个词是两个有细微区别的。硬件中,寄存器直接将它的输入和输出线连接到电路的其他部分,机器级编程中,寄存器代表的是CPU中为数不多的可寻址的字,这里的地址是寄存器ID。分别称呼为"硬件寄存器""程序寄存器"
寄存器操作:
寄存器文件有两个读端口还有一个写端口。这样一个多端口随机访问存储器允许同时进行读和写操作。
想寄存器文件写入字是由时钟信号控制的,控制方式类似于将值加载到时钟寄存器。
双端口的存储器:一个用来读指令,另一个用来读或者写数据。
4.3 Y86的顺序实现
4.3.1将处理组织成阶段
取值:从存储器读取指令字节,地址为程序计数器PC的值。
译码:译码阶段从寄存器文件读入最多两个操作数。
执行:ALU要么执行指明的操作,计算存储器引用的有效地址,要么增加或减少栈指针。
访存:可以将数据写入存储器或者从存储器读出数据。
写会:最多可以写两个结果到寄存器文件。
更新PC:将PC设置成下一条指令的地址。
降低复杂度的一种方法是让不同的指令共享尽量多的硬件。
Y86指令序列:
执行rrmovl指令和执行算术运算类似,不过不需要取第二个寄存器操作数。
Y86指令pushl和popl在顺序实现中的计算:
三类控制转移指令的处理:各种跳转、call和ret
Y86指令jXX、call和ret在顺序实现中的计算:
对指令call我们要将valP也就是call指令后紧跟着的那条指令的地址压入栈中。在更新PC阶段将PC设为valC也就是调用的目的地。对指令ret在更新PC阶段我们将valM从栈中取出的值赋给PC。
4.3.2 SEQ硬件结构
实现所有Y86指令所需要的计算可以组织成6个基本阶段:取指,译码,执行,访存,写回和更新PC。
取指:将程序计数器寄存器作为地址,指令存储器读取指令的字节。
译码:寄存器文件有两个读端口从这两个端口同时读寄存器值valA和valB
条件码寄存器有三个条件码位
访存:在执行访存操作时,数据存储器读出或写入一个寄存器字。指令和数据存储器访问的是相同的存储器位置但是用于不同的目的。
写回:寄存器文件有两个写端口。E用来写ALU计算出来的值,而端口M用来写从数据存储器中读出的值。
4.3.3 SEQ的时序
SEQ的实现包括组合逻辑和两种存储器设备:时钟寄存器(程序计数器和条件码寄存器),随机访问存储器(寄存器文件、指令存储器和数据存储器)。组合逻辑不需要任何时序或控制——只要输入变化,值就会通过逻辑门网络传播。
每个时钟周期,程序计数器都会装在新的指令地址,只有在执行整数运算指令时,才会装在条件码寄存器,只有偶在执行rmmovl、pushl或call指令时,才会写数据存储器。寄存器文件的两个写端口允许每个时钟周期更新2个程序寄存器。
要控制处理其中的活动时序,只需要寄存器和存储器的时钟控制。
——处理器从来不需要为了完成一条指令的执行而去读由该指令更新了的状态。
SEQ硬件结构:
标识顺序实现的不同计算步骤:
4.3.4 SEQ阶段的实现
HCL描述中使用的常数值:
- 取指阶段
包括指令存储器硬件单元
- 译码和写回阶段
寄存器文件有四个端口。它支持同时进行两个读和两个写,每个端口都有一个地址连接和一个数据连接,地址链接是一个寄存器ID而数据链接是一组32根线路,即可以作为寄存器文件的输出字,也可以作为它的输入字。
- 执行阶段
包括ALU,它通常是作为加法器来使用。还包括条件码寄存器。ALU每次运行都会产生三个与条件码相关的信号——零、符号和溢出。
标号为"cond"的硬件单云会根据条件码和功能码来确定是否进行条件分支或者条件数据传送
- 访存阶段
任务就是读或者写程序数据
- 更新PC阶段
最后一个阶段会产生程序计数器的新值
- SEQ小结
唯一的问题就是太慢了,时钟必须非常慢,以使得信号能在一个周期内传播所有的阶段。
4.4流水线的通用原理
流水线化的一个重要特性就是增加了系统的吞吐量,也就是单位时间内服务的顾客总数,不过他也会轻微增加延迟,也就是服务一个用户所所需要的时间。
4.4.1 计算流水线
现代逻辑设计中,电路延迟以微微秒作为单位计算。我们以每秒千兆条指令也就是每秒十亿条指令,为单位来描述吞吐量。从头到尾执行一条指令所需要的时间称为延迟。
4.4.2流水线操作的详细说明
4.4.3 流水线的局限性
1.不一致的划分
2.流水线过深,受益反而下降
4.4.4带反馈的流水线系统
每一对相邻的指令之间都有数据相关
另一种相关是由于指令控制流造成的顺序相关
4.5 Y86的流水线实现
4.5.1 SEQ+:重新安排计算阶段
SEQ到SEQ+中队状态元素的改变是一种通用的改进例子,这种改进称为电路重定时。重定时改变了一个系统的状态表示,但是并不改变他的逻辑行为。通常用它来平衡一个系统中各个阶段之间的延迟。
4.5.2插入流水线寄存器
SEQ+的各个阶段之间插入流水线寄存器,并对信号重新排列得到PIPE—处理器,性能稍差一点。
4.5.3对信号进行重新排列和标号
最系统的方法就是让与每条指令关联的状态码与指令一起通过流水线。
4.5.4预计下一个PC
流水线化设计的目的就是每个时钟周期都发射一条新指令,也就是说每个时钟周期都有一条新指令进入执行阶段并最终完成。要是达到这个目的就意味着吞吐量是每个时钟周期一条指令。
我们的设计使用总是选择分支的预测策略。
4.5.5 流水线冒险
PEPE-结构是创建一个流水线化的Y86处理器的好开端。冒险分为两类:数据冒险和控制冒险。
4.5.6用暂停来避免数据冒险
暂停时避免冒险的一种常用技术,暂停时,处理器会停止流水线一条或多条指令,直到冒险条件不再满足。
暂停技术就是让一组指令阻塞在他们所处的阶段,而允许其他指令继续通过流水线。
4.5.7用转发来避免数据冒险
将结果只直接从一个流水线阶段传到较早阶段的技术叫做数据转发,或是转发,有时称为旁路。
4.5.8 加载/使用数据冒险
有一类数据冒险不能单纯用转发来解决,因为存储器读在流水线发生的比较晚。
用暂停来处理加载/使用冒险的方法称为加载互锁,加载互锁和转发技术结合起来足以处理所有可能类型的数据冒险
4.5.9异常处理
异常可以由程序执行从内部产生,也可以有某个外部信号从外部产生。我们的指令集体系结构包括三种不同的内部异常:1.halt指令 2.由非法指令和功能码组合的指令 3.取指或数据读写试图访问一个非法地址
我们把导致异常的指令称为异常指令。
异常处理包括一些细节问题。首先可能同时又多条指令会引起异常,第二个细节问题是,当首先取出一条指令,开始执行时,导致了一个异常,而后来由于分支预测错误,取消了该指令。第三个细节问题的产生是因为流水线化的处理器会在不同的阶段更新系统状态的不同部分。
为了避免异常指令之后的指令更新任何程序员可见的状态,当处于访存或者写回状态中的指令导致异常时,流水线控制逻辑必须禁止更新条件码寄存器或是数据存储器。
4.5.10 PIPE各阶段的实现
1.PC选择和取指阶段
2.译码和写回阶段
3.执行阶段
4.访存阶段
4.5.11流水线控制逻辑
处理ret:流水线必须暂停直到ret指令到达写回阶段
加载/使用冒险:在一条从存储器中读取一个值的指令和一条使用该值的指令之间,流水线必须暂停一个周期
预测错误的分支:在分支逻辑发现不应该选择分支之前,分支目标处的几条指令已经进入流水线了,必须从流水线中去掉这些指令。
异常:当一条指令导致异常,我们想要禁止后面的指令更新程序员可见状态,并且在异常指令到达写回阶段时,停止执行。
- 特殊控制情况所期望的处理
- 发现特殊控制条件
- 流水线控制机制
- 控制条件的组合
- 控制逻辑实现
4.6小结
ISA在处理器行为和如何实现处理器之间提供了一层抽象。ISA提供了程序执行的一种顺序说明,也就是一条指令执行完了,下一条指令才会开始。
ISA既有RISC指令集的属性,也有CISC指令集的属性。
流水线化通过让不同的阶段并行操作,改进了系统的吞吐量性能。
重要经验:
·管理复杂性是首要问题
·不需要直接实现ISA
·硬件设计人员必须非常谨慎小心