第五次学习笔记
20135221黄卫第5次学习记录
第四章 处理器体系结构
Y86指令集结构
对于Y86来说,它的程序猿可见状态就是这几种: 寄存器、存储器、条件码、PC、程序状态。
在Y86当中,寄存器依旧是8个,每一个寄存器可以存储一个字,也就是一个32位二进制。条件码是一个一位二进制的寄存器,保存着最近的算术或逻辑运算所造成的影响的信息。PC则是程序计数器,记录当前正在执行的指令的地址。
存储器则是一个很大的字节数组,Y86的程序可以使用虚拟地址(类似于数组的下标)来访问存储器,硬件和操作系统会将虚拟地址翻译为实际的地址。最后一个程序状态(stat),它则代表着程序的运行情况。
以上便是程序猿可见的状态,或者说机器级程序可访问的CPU状态,我们在设计和实现一个处理器的时候,就是设计一系列指令去操作这些状态。
Y86指令
1.在movl指令中,指令名字的第一个字母就表明了源类型。指令第二个字母指明了目的类型。立即数(i)、寄存器(r)、存储器(m)。两个存储器传送指令中的存储器引用方式是简单地基址和偏移量形式。
2.addl,subl,andl,xorl是四个整数操作指令,Y86中只允许对寄存器数据进行操作。
3.jmp,jle,jl,je,jne,jge,jg是七个跳转指令,根据分支指令的类型和条件码的设置来选择分支。
4.cmovle,cmovl,cmove,cmovne,cmovge,cmovg是六个条件传送指令,这些指令的格式与寄存器-寄存器传送指令rrmovl一样,但只有当条件码满足所需要的约束时,才会更新目的寄存器的值。
5.call指令将返回地址入栈,然后跳到目的地址。
6.pushl和popl指令实现了入栈和出栈。
7.halt指令停止指令的执行(IA32中的指令hlt)。
指令编码
每条指令的第一个字节表明指令的类型。这个字节分为两个部分,每部分4位:高4位是代码部分,低4位是功能部分。功能值只有在一组相关指令共用一个代码时才有用。
- 整数操作里代码部分均为6,功能部分区分addl,subl,andl,xorl
- 分支指令里代码部分均为7
- 传送指令里代码部分均为2
- 8个程序寄存器中每个都有相应的0~7的寄存器标识符。
程序寄存器存在一个寄存器文件中,这个寄存器文件就是一个小的、以寄存器ID作为地址的随机访问存储器。当需要指明不应访问任何寄存器时,用ID值0xF表示。
- 有的指令没有寄存器操作数(分支指令和call指令),就没有寄存器指示符字节。
- 只需要一个寄存器操作数的指令(irmovl、pushl、popl),将另一个寄存器指示符设为0xF。
-
有的指令需要一个附加的4字节常数字,可作为:irmovl的立即数数据,rmmovl和mrmovl的地址指示符偏移量,分支指令和调用指令的目的地址。
注意: - 分支指令和调用指令的目的地址是一个相对地址,而不是相对寻址方式。 - 所有整数采用小端法编码。当指令按反汇编格式书写时这些字节就以相反的顺序出现。
- 指令集的一个重要性质就是字节编码必须有唯一的解释。这个性质保证了处理器可以无二义性地执行目标代码程序。即使代码嵌入在程序的其他字节中,只要从序列的第一个字节开始处理,我们仍然可以很容易地确定指令序列。反过来说,如果不知道一段代码序列的起始位置,我们就不能准确地确定怎样将序列划分成单独的指令。
Y86异常
Y86程序
书中给出了一个示例程序,来说明X86和Y86的区别,其实两者是非常相似的,区别就在于,有的时候Y86需要两条指令来达到X86一条指令就可以达成的目的。
比如对于X86指令中的 addl $4,%ecx 这样的指令,由于Y86当中的addl指令中不包含立即数,所以Y86需要先将立即数存入寄存器,即使用irmovl指令,然后再使用addl来处理加法运算。
总的来说,Y86就是一个X86的缩减版,它的目的是以简单的结构实现一个处理器,帮助我们了解处理器的设计和实现。有兴趣的猿友可以去观摩一下Y86程序生成的汇编代码,并进行逐一的分析,实际上,这与X86是十分类似的
一些Y86指令的详情
大多数Y86指令是以一种直接的方式修改程序状态的。
执行pushl和popl指令时,处理器的行为是不确定的,因为要入栈的寄存器会被同一条指令修改。通常有两种约定:
- 压入/弹出%esp的原始值
- 压入/弹出%esp-/+4后的值
逻辑设计和硬件控制语言HCL
电子电路中,用1.0V左右的高电压表示逻辑1,用0.0V左右的低电压表示逻辑0.
逻辑门
1.逻辑门产生的输出,等于它们输入位值的某个布尔函数。
2.
AND &&
OR ||
NOT !
3.逻辑门只对单个位的数进行操作,而不是整个字。
4.逻辑门总是活动的,输入变化输出很快就跟着变化。
组合电路和HCL布尔表达式。
两个限制:
- 两个或多个逻辑门的输出不能连在一起
- 这个网必须是无环的
字级的组合电路和HCL整数表达式
在HCL中,多路复用函数是用情况表达式来描述的,格式如下:
[
select_1 : expr_1
select_2 : expr_2
...
select_k : expr_k
]
集合关系
判断集合关系:
iexpr in {iexpr1,iexpr2,...,iexprk}
其中被测值iexpr和待匹配的值iexpr1-iexprk
存储器和时钟
时序电路:有状态,且在这个状态上进行计算的系统。
时序电路的两类存储器设备
- 时钟寄存器(寄存器):储存单个位或字,用时钟信号控制寄存器加载输入值。
- 随机访问储存器(储存器):储存多个字,用地址选择该读/写哪个字。
硬件和机器级编程中的寄存器有细微差别,分为称为“硬件寄存器”和“程序寄存器”。
Y86处理器会用时钟寄存器保存程序计数器PC,条件代码CC和程序状态Stat。
处理器有一个随机访问存储器来存储程序数据。
处理器还包括另外一个只读存储器,用来读指令。
在大多数实际系统中,这两个存储器被合并为一个具有双端口的存储器:一个用来读指令,一个用来读或写数据。
第三节 Y86的顺序实现
将处理组织成阶段
1.取指
2.译码
3.执行
4.访问
5.写回
6.更新PC
SEQ硬件结构
1.取指
2.译码
3.执行
4.访存
5.写回
SEQ的时序
四个硬件单元:
1.程序计数器
2.条件码寄存器
3.数据存储器
4.寄存器文件
由于Y86指令集得本质,要遵循以下原则组织计算:
处理器从来不需要为了完成一条指令的执行而去读由该指令更新了的状态
SEQ阶段的实现
- 取指阶段,包括指令储存器硬件单元
- 译码和回写阶段
- 执行阶段,包括算数/逻辑单元
- 访存阶段,读或写程序数据
- 更新PC阶段
- SEQ小结
流水线的通用原理
流水线化的重要特性
增加了系统的吞吐量,即单位时间内服务的顾客总数,不过也会轻微的增加执行时间,即服务一个用户需要的时间。
处理器设计的几个重要经验:
- 管理复杂性是首要问题,尽量保持硬件设计的简单。
- 不需要直接实现ISA。
- 一开始就保证设计正确是非常重要的
PIPE-结构
创建一个流水线化的Y86处理器的好开端。但是,将流水线技术引入一个带反馈的系统,当相邻指令同存在相关时会导致出现问题。
相关的两种形式
- 数据相关 下一条指令会用到这条指令计算出的结果;
- 控制相关 一条指令要确定下一条指令的位置,例如在执行跳转、调用或返回指令时,这些相关可能会导致流水线产生计算错误,称为冒险。同相关一样,冒险也可以分为两类:数据冒险和控制冒险。
流水线控制逻辑
这个逻辑必须处理以下4种控制情况,这些情况是其他机制(例如数据转发和分支预测)不能能处理的:
处理ret 流水线必须暂停直到ret指令到达写回阶段。
加载/使用冒险 流水线必须暂停一个周期。
预测错误的分支 在分支逻辑发现不应该选择分支之前,分支目标处的几条指令已经进流水线了。必须从流水线中去掉这些指令。
异常 当―条指令导致异常,我们想要禁止后面的指令更新程序员可见的状态,并睏异常指令到达写回阶段时,停止执行。
参考资料1:深入理解计算机系统
参考资料2:(实验楼)深入理解计算机系统:实验五
参考资料3:ubuntu12.04 安装CS:APP Y86模拟器
实验