信息安全系统设计基础第六周学习总结
第六周(10.12-10.18):
学习计时:共12小时
读书:4
代码:1
作业:3
博客:4
第四章 处理器体系结构
现代微处理器可以称得上是人类创造的最复杂的系统之一。一块手指甲大小的硅片上,可以容纳一个完整的高性能处理器、大的高速缓存,以及用来连接到外部设备的逻辑电路。
- 到目前为止,我们看到的计算机系统只限于机器语言程序级。我们知道处理器必须执行系列指令,每条指令执行某个简单操作,例如两个数相加。指令被编码为由一个或多个字节序列组成的二进制格式。
- 不同的处理器“家族”,例如intel ia32性能和复杂性不断提高,但是不同的型号在ISA级别上都保持着兼容。一些常见的处理器家族(例如IA32)中的处理器分别由多个厂商提供。
4. 1Y86指令集体系结构
4.1.1程序员可见的状态
- Y86程序中的每条指令都会读取或修改处理器状态的某些部分。这称为程序员可见状态。这里的“程序员”既可以是用汇编代码写程序的人,也可以是产生机器级代码的编译器。在处理器实现中,只要我们保证机器级程序能够访问程序员可见状态,就不需要完全按照ISA隐含的方式来表示和组织这个处理器状态。Y86的处理器状态类似于IA32。
- 有8个程序寄存器:%eax、%ecx、%edx、%ebx、%esi、%edi、%esp和%ebp。处理器的每个程序寄存器存储一个字。
- 程序计数器存放当前正在执行指令的地址。
4.1.2Y86指令
- Y86指令集基本上是IA32指令集的一个子集。它只包括四字节整数操作,寻址方式比较少,操作也较少。
- 四字节数据,所以称之为“字”不会有歧义。
- 汇编代码格式类似于IA32的ATT格式。
4.1.3指令编码
- 每条指令需要1~6个字节不等,这取决于需要哪些字段。
- Y86中的寄存器编号跟IA32中的相同。程序寄存器存在CPU中的一个寄存器文件中,这个寄存器文件就
是一个小的、以寄存器ID作为地址的随机访问存储器。在指令编码中以及在我们的硬件设计中,当需要指明不应访问任何寄存器时,就用ID值0xF来表示。 - 有的指令只有一个字节长,而有的需要操作数的指令编码就更长一些。首先,可能有附加的寄存器指示符字节,指定一个或两个寄存器。
- 从指令的汇编代码表示中可以看到,根据指令类型,指令可以指定用于数据源和目的的寄存器,或是用于地址计算的基址寄存器。没有寄存器操作数的指令,例如分支指令和call指令,就没有寄存器指示符字节。那些只需要一个寄存器操作数的指令将另一个寄存器指示符设为OxF。这种约定在我们的处理器实现中非常有用。
- 有些指令需要一个附加的4字节常数字。
4.1.4Y86异常
对于Y86,当遇到这些异常的时候,我们就简单地让处理器停止执行指令。在更完整的的设计中,处理器通常会调用一个异常处理程序,这个过程被指定用来处理遇到的某种类型的异常。就像在第8章中讲述的,异常处理程序可以被配置成不同的结果,例如,放弃程序或者调用一个用户自定义的信号处理程序。
4.1.5Y86程序
程序中以“.”开头的词是汇编器命令。
4.1.6一些Y86的详情
- 大多数Y86指令是以一种直接的方式修改程序状态的,所以定义每条指令想要达到的结果并不困难。不过,两个特别的指令组合需要特别注意一下。pushl指令会把栈指针减4,并且将一个寄存器值写入存储器中。因此,当执行pushl %esp指令时,处理器的行为是不确定的,因为要入栈的寄存器会被同一条指令修改。
- 通常有两种约定:1)压入%esp的原始值,2)压入减去4的%esp的值。
4. 2逻辑设计和硬件控制语言HCL
4.2.1逻辑门
4.2.2组合电路和HCL布尔表达式
图4-11多路复用器根据输入控制信号的值,从一组不同的数据信号中选出一个,在这个单个位的多路复用器中,两个数据信号是输入位a和b,控制信号是输入位s,当s为1时,输出等于a:而当s为0时,输出等于b。在这个电路中,我们可以看出两个AND门决定了是否将它们相对应的数据输入传送到OR门。
HCL表达式很清楚地表明了组合逻辑电路和C语言中逻辑表达式的对应之处。它们都是用布尔操作来对输入进行计算的函数。值得注意的是,这两种表达计算的方法之间有以下区别:
因为组合电路是由一系列的逻辑门组成,它的属性是输出会持续地响应输入的变化。如果电路的输入变化了,在一定的延时之后,输出也会相应的变化。相比之下,C表达式只会在程序执行过程中被遇到时才进行求值。
C的逻辑表达式允许参数是任意整数,0表示FALSE,其他任何值都表示TRUE。而逻辑门只对位值0和1进行操作.
C的逻辑表达式有个属性就是它们可能只被部分求值。如果―个AND或OR操作的结果只用对第一个参数求值就能确定,那么就不会对第二个参数求值了。
4.2.3字级的组合电路和HCL整数表达式
- 通过将逻辑门组合成大的网,可以构造出能计算更加复杂函数的组合电路。通常,我们设计能对数据字进行操作的电路。有一些位级信号代表一个整数或一些控制模式。例如我们的处理器设计将包含有很多字,字的大小为4位和32位,代表整数、地址、指令代码和寄存器标识符。
- 执行字级计算的组合电路根据输入字的各个位,用逻辑门来计算输出字的各个位。
- 选择表达式可以是任意的布尔表达式,可以有任意多的情况。这就使得情况表达式能描述带复杂选择标准的、多种输入信号的块。
4.2.4集合关系
在处理器设计中,很多时候都需要将一个信号与许多可能匹配的信号做比较,以此来检测正在处理的某个指令代码是否属于某一类指令代码。
4.2.5存储器和时钟
为了产生时序电路,我们必须引入按位存储信息的设备。存储设备都是由同一个时钟控制,时钟是一个周期性信号,决定什么时候要把新值加载到设备中。考虑两类存储器设备:
1.时钟寄存器(简称寄存器)存储单个位或字。时钟信号控制寄存器加载输入值。
2.随机访问存储器(简称存储器)存储多个字,用地址来选择该读或该写哪个字。随机访问存储器的例子包括:1)处理器的虚拟存储器系统,硬件和操作系统软件结合起来使处理器可以在一个很大的地址空间内访问任意的字;2)寄存器文件,在此,寄存器标识符作为地址。在IA32或Y86处理器中,寄存器文件有8个程序寄存器。
大多数时候,寄存器都保持在稳定状态(用×表示)产生的输出等于它的当前状态。信号沿着寄存器前面的组合逻辑传播这时,产生了一个新的寄存器输入(用y表示)但只要时钟是低电位的,寄存器的输出就仍然保持不变。当时钟变成高电位的时候,输入信号就加载到寄存器中,成为下一个状态y直到下一个时钟上升沿,这个状态就一直是寄存器的新输出。关键是寄存器是作为电路不同部分中的组合逻辑之间的屏障。每当每个时钟到达上升沿时,值才会从寄存器的输入传送至输出。
4.3 y86的顺序(sequential)实现
4.3.1将处理组织成阶段
通常,处理一条指令包括很多操作。将它们组织成某个特殊的阶段序列,即使指令的动作差异很大,但所有的指令都遵循统一的序列。每一步的具体操作取决于正在执行的指令。创建这样的框架,我们便能设计一个充分利用硬件的处理器。简略描述:
取指
译码
执行
访存
写回
更新PC
我们面临的一个挑战是将每条不同指令所需要的计算放入到上述那个通用框架中。我们会使用图4-17中所示的代码来描述不同Y86指令的处理。表中的这种格式很容易映射到硬件,表中的每一行都描述了一个信号或存储状态的分配。阅读时可以把它看成是从上至下的顺序求值。当我们将这些计算映射到硬件时,会发现其实并不需要严格按照顺序来执行这些求值。
4.3.2SEQ硬件结构
硬件单元与各个处理阶段相关联:
- 取指:将程序计数器寄存器作为地址,指令存储器读取指令的字节。
- 译码:寄存器文件有两个读端口A和B,从这两个端口同时读寄存器值
- 执行:执行阶段会根据指令的类型,将算术/逻辑单元用于不同的目的。对整数操作,它要执行指令所指定的运算。对其他指令,它会作为一个加法器来计算增加或减少栈指针,或者计算有效地址,或者只是简单地加0,将一个输入传递到输出。
- 访问:在执行访问操作时,数据存储器读出或写入一个存储器字。
- 写回:寄存器文件有两个写端口。
4.3.3SEQ的时序
SEQ的实现包括组合逻辑和两种存储器设备:时钟寄存器,随机访问存储器(寄存器文件、指令存储器和数据存储器)。组合逻辑不需要任何时序或控制。对于较小的存储器来说(例如寄存器文件)这是一个合理的假设,而对于较大的电路来说,可以用特殊的时钟电路来模拟这个效果。由于指令存储器只用来读指令,因此我们可以将这个单元看成是组合逻辑。
4.3.4SEQ阶段的实现
寄存器文件有四个端口,它支持同时进行两个读(在端口A和B上)和两个写(在端口E和M)。每个端口都有一个地址连接和―个数据连接,地址连接是一个寄存器ID,而数据连接是一组32根线路,既可以作为寄存器文件的输出字,也可以作为它的输入字。如果某个地址端口上的值为特殊标识符0xF,则表明不需要访问寄存器。
4.4 流水线的通用原理
4.4.1计算流水线
在现代逻辑设计中,电路延迟以微微秒,也就是10的负12次方秒为单位来计算。
4.4.2流水线操作的详细说明
为了更好地理解流水线是怎样工作的,详细看看流水线计算的时序和操作。图4-34是三阶段流水线的流水线图,流水线阶段之间的指令转移是由时钟信号来控制的"每隔120ps,信号从0上升至1开始下一组流水线阶段的计算。
4.4.3流水线的局限性
4.4.4带反馈的流水线系统
4.5 y86的流水线实现
4.5.1SEQ+重新安排计算阶段
作为实现流水线化设计的一个过渡步骤,我们必须稍微调整一下SEQ中五个阶段的顺序,使得更新PC阶段在一个时钟周期开始时执行,而不是结束时才执行。只需要对整体硬件结构做最小的改动,对于流水线阶段中的活动的时序,它能工作得更好。我们称这和修改过的设计为“SEQ+”。我们移动PC阶段,使得它的逻辑在时钟周期开始时活动,使它计算当前指令的PC值。
4.5.2插入流水线寄存器
4.5.3对信号进行重新排列和标号
顺序实现SEQ和SEQ+在一个时刻只处理一条指令。在流水线化的设计中,与各个指令相关联的值有多个版本,会随着指令一起流过系统。我们需要很小心以确保使用的是正确版本确版本的信号,否则会导致很严重的错误。通过在信号名前面加上大写的流水线寄存器名字作为前缀,存储在流水线寄存器中的信号可以唯一的被标识。
4.5.4预测下一个PC
在PIPE―设计中,我们采取了一些措施来正确处理控制相关。流水线化设计的目的就是每个时钟周期都发射一条新指令,也就是说每个时钟周期都有一条新指令进入执行阶段并最终完成。要是达到这个目的就意味着吞吐量是每个时钟周期一条指令。要做到这一点,我们必须在取出当前指令之后,马上确定下一条指令的位置。不幸的是,如果取出的指令是条件分支指令,要到几个周期后,也就是指令通过执行阶段之后,我们才能知道是否要选择分支。类似地,如果取出的指令是ret,要到指令通过访存阶段,才能确定返回地址。
4.5.5流水线冒险
PIPE-结构是创建一个流水线化的Y86处理器的好开端。不过,回忆4.44节中的讨论,将流水线技术引入一个带反馈的系统,当相邻指令同存在相关时会导致出现问题。在完成我们的设计之前,必须解决这个问题。
这些相关有两种形式:
1)数据相关,下一条指令会用到这条指令计算出的结果;
2)控制相关,一条指令要确定下一条指令的位置,例如在执行跳转、调用或返回指令时,这些相关可能会导致流水线产生计算错误,称为冒险。同相关一样,冒险也可以分为两类:数据冒险和控制冒险。
4.5.6用暂停来避免数据冒险
暂停是避免冒险的―种常用技术,暂停时,处理器会停止流水线中一条或多条指令,直到冒险条件不再满足,让一条指令停顿在译码阶段,直到产生它的源操作数的指令通过了写回阶段,这样我们的处理器就能避免数据冒险,。它对流水线控制逻辑做了一些简单的加强。当指令addl处于译码阶段时,流水线控制逻辑发现执行、访存或写回阶段中至少有―条指令会更新寄存器。
4.5.7用转发来避免数据冒险
为了充分利用数据转发技术,我们还可以将新计算出来的值从执行阶段传到译码阶段,以避免程序prog4所需要的暂停。在周期4中,译码阶段逻辑发现在访存阶段中有对寄存器%edX未进行的写,而且执行阶段中ALU正在计算的值稍后也会写入寄存器%eaX。它可以将访存阶段中的值作为操作数Va1A也可以将ALU的输出作为操作数~Va1B,注意,使用ALU的输出不会导致任何时序问题,译码阶段只要在时钟周期结束之前产生信号Va1A和Va1B,在时钟上升开始下一个周期时,流水线寄存器E就能装载来自译码阶段的值,而在此之前ALU的输出已经是合法的了。
4.5.8加载/使用数据冒险
有类数据冒险不能单纯用转发来解决,因为存储器在流水线发生的比较晚。
4.5.9异常处理
我们的指令集体系结构包括三种不同的内部产生的异常:1:)halt指令,2)有非法指令和功能码组合的指令, 3)取指或数据读写试图访问一个非法地址。正确处理异常是任何微处理器设计中很有挑战性的一面。异常可能出现在不可预测的时间,需要明确的中断通过处理器流水线的指令流。
4.5.10PIPE各阶段的实现
4.5.11流水线控制逻辑
现在准备创建流水线控制逻辑,以完成我们的PIPE设计。这个逻辑必须处理以下4种控制情况,这些情况是其他机制(例如数据转发和分支预测)不能能处理的:
处理ret:流水线必须暂停直到ret指令到达写回阶段。
加载/使用冒险:流水线必须暂停一个周期。
预测错误的分支:在分支逻辑发现不应该选择分支之前,分支目标处的几条指令已经进流水线了。必须从流水线中去掉这些指令。
异常:当―条指令导致异常,我们想要禁止后面的指令更新程序员可见的状态,并睏异常指令到达写回阶段时,停止执行。
我们先浏览每种情况所期望的行为,然后再设计处理这些情况的控制逻辑。
4.5.12性能分析
我们可以看到,所有需要流水线控制逻辑进行特殊处理的条件,都会导致流水线不能够实现每个时钟周期发射一条新指令的目标。我们可以通过确定往流水线中插入气泡的频率,来衡量这种效率的损失。因为插入气泡会引发未使用的流水线周期。一条返回指令会产生三个气泡,一个加载/使用冒险会产生一个,而一个预测错误的分支会产生两个。
4.5.13未完成的工作
- 多周期指令
- 与存储系统的接口
4.6 小结
重点
- 第六周:学习任务教材 第四章
- 本章内容是处理器体系结构,重点掌握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
实验楼实验
过程
构建YIS环境:
cd ~/Code/shiyanlou_cs413
wget http://labfile.oss.aliyuncs.com/courses/413/sim.tar
tar -xvf sim.tar
cd sim
sudo apt-get install tk
sudo ln -s /usr/lib/x86_64-linux-gnu/libtk8.6.so /usr/lib/libtk.so
sudo ln -s /usr/lib/x86_64-linux-gnu/libtk8.6.so /usr/lib/libtk.so
makeYIS测试:
cd y86-code
进入测试代码,教材p239页代码为asuml.ys,可以通过
make asuml.yo
进行汇编,asuml.yo就是汇编后的结果,见教材p238。
make all
可以汇编运行所有代码结果。
遇到的问题
在实验楼中无法解析主机地址
还有不太清楚实验楼中第一项任务的要求。
解决方法:在答疑论坛中看到了同学的提问和老师的回复。
实验楼普通用户不能联外网,所以不可以解析外部的网址,目前外网权限只对会员开放了。老师在实验楼工作人员的帮助下,已经修改了实验指导书,把外网地址改成内网地址了。
参考资料
- 教材:第四章《处理器体系结构》,详细学习指导:http://group.cnblogs.com/topic/73069.html
- 课程资料:https://www.shiyanlou.com/courses/413 实验五,课程邀请码:W7FQKW4Y
- 教材中代码运行、思考一下,读代码的学习方法:http://www.cnblogs.com/rocedu/p/4837092.html。
- 鼓励自己好好读书的链接,但说是入门级的书,可是我还是东西很多都看不懂:http://www.cnblogs.com/JeffreyZhao/archive/2009/11/23/recommended-reading-3-csapp.html
- 无意中翻到的一个程序员的故事:http://mindhacks.cn/2009/05/17/seven-years-in-nju/
感悟
- 遇到问题后我用过百度用各种方式查找实验的问题,在不同的电脑上测试,果然还是答疑论坛最管用了。。。
- markdown真的很方便。
- 很多人说这本书是入门级教程,但是还是觉得不容易看懂。