• 处理器体系结构


    Y86指令集结构

    对于Y86来说,它的程序猿可见状态就是这几种: 寄存器、存储器、条件码、PC、程序状态。

    在Y86当中,寄存器依旧是8个,每一个寄存器可以存储一个字,也就是一个32位二进制。条件码是一个一位二进制的寄存器,保存着最近的算术或逻辑运算所造成的影响的信息。PC则是程序计数器,记录当前正在执行的指令的地址。

    存储器则是一个很大的字节数组,Y86的程序可以使用虚拟地址(类似于数组的下标)来访问存储器,硬件和操作系统会将虚拟地址翻译为实际的地址。最后一个程序状态(stat),它则代表着程序的运行情况。

    以上便是程序猿可见的状态,或者说机器级程序可访问的CPU状态,我们在设计和实现一个处理器的时候,就是设计一系列指令去操作这些状态。

    Y86指令集

    接下来我们就看看Y86的指令集,这里LZ就直接上图了,这些指令其实都是从X86的指令集YY而来。

    上面的指令相信大家都不会太陌生,LZ这里就不仔细的解释了,下面我们只简单的把每个指令的作用过一遍。

    halt:这个指令将会终止指令的执行。

    nop:这是一个占位指令,它不做任何事情,后续为了实现流水线,它有一定的作用。

    xxmovl:这是一系列的数据传送指令,其中r代表寄存器,m代表存储器,i代表立即数。比如rrmovl指令,则代表将一个寄存器的值,赋给另外一个寄存器。

    opl:操作指令,比如加法,减法等等。

    jxx:条件跳转指令,根据后面的条件进行跳转。

    cmovxx:条件传送指令,后面的xx代表的是条件。特别的是,条件传送只发生在两个寄存器之间,不会将数据传送到存储器。

    call与ret:方法的调用和返回指令。一个将返回地址入栈,并跳到目标地址。一个将返回地址入PC,并跳到返回地址。

    push与pop:入栈和出栈操作。

    指令编码

    在图的右边,是指令所占的字节数或者说编码。一般两个寄存器占用一个字节,存储器则占用四个字节,指令的编码和功能占用一个字节。因此可以看到,比如rrmovl指令,它的字节长度是2,其中第一个字节代表了指令rrmovl,第二个字节代表了两个寄存器。

    对于opl、jxx、cmovxx指令来说,都有一个fn标识,占用4个二进制位(半个字节)。这个便是指令的功能部分,这个是由于它们的指令编码一样,但功能有所不同所造成的。比如对于opl,就有加、减、与、异或等操作,那么它们的指令编码第一个字节就分别为十六进制的60、61、62、63。

    对于寄存器的表示,是使用4个二进制位表示的,这是一个ID标识。所有的寄存器可以看做是一个寄存器文件,其中的ID标识就类似于它们的地址。对于一些只需要一个寄存器的指令来说,另一个寄存器标识位使用0xF表示。

    还有的指令需要一个字的常数,比如irmovl指令,call指令等等。这种指令,将把常数放在最后的四个字节当中,顺序按照大端法或小端法表示(与机器和OS有关)。对于call指令来说,这四个字节就是一个地址,这个地址就是绝对地址,指向了存储器当中的某一个位置,这个位置存储着代码。采用绝对地址是为了描述简单,真实当中,是采取的基于PC的相对地址。

    Y86异常

    对于Y86来说,程序猿可见的状态中就有stat状态码,它标识了程序执行的状态。Y86需要有能力根据stat去做一些处理。不过为了简单起见,这里除了正常执行之外,都将停止指令的执行。真实当中,会有专门的异常处理程序。

    Y86有四种不同的状态码,AOK(正常)、HLT(执行halt指令)、ADR(非法地址)和INS(非法指令)。

    Y86程序

    书中给出了一个示例程序,来说明X86和Y86的区别,其实两者是非常相似的,区别就在于,有的时候Y86需要两条指令来达到X86一条指令就可以达成的目的。

    比如对于X86指令中的 addl $4,%ecx 这样的指令,由于Y86当中的addl指令中不包含立即数,所以Y86需要先将立即数存入寄存器,即使用irmovl指令,然后再使用addl来处理加法运算。

    总的来说,Y86就是一个X86的缩减版,它的目的是以简单的结构实现一个处理器,帮助我们了解处理器的设计和实现。有兴趣的猿友可以去观摩一下Y86程序生成的汇编代码,并进行逐一的分析,实际上,这与X86是十分类似的。

     

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

    电子电路中,用1.0V左右的高电压表示逻辑1,用0.0V左右的低电压表示逻辑0.

    一、逻辑门

    1.逻辑门产生的输出,等于它们输入位值的某个布尔函数。

    2.

    AND &&
    OR ||
    NOT !

    3.逻辑门只对单个位的数进行操作,而不是整个字。

    4.逻辑门总是活动的,输入变化输出很快就跟着变化。

    二、组合电路和HCL布尔表达式

    1.构建计算块(组合电路)时的限制

    • 两个或多个逻辑门的输出不能连接在一起
    • 必须无环

    2.组合逻辑电路和c语言中逻辑表达式的区别

    • 组合电路的输出会持续响应输入变化,c语言表达式只有在执行过程中被遇到才求值
    • 逻辑门只对0和1操作,c语言表达式中参数可以是任意整数,0是FALSE,不是0的都是TRUE
    • c的逻辑表达式可能被部分求值

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

    • 所有字级的信号都声明为int,不指定字的大小
    • 多路复用函数用情况表达式来描述,具体格式如下:

      [
      	select_1 : expr_1
      	select_2 : expr_2
      	……
      ]

      从逻辑上讲,这些选择表达式是顺序求值的。

    • 选择表达式为1时,表示如果前面没有情况被选中,就选择这种情况
    • 不同 选择表达式之间允许不互斥

    四、集合关系

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

    iexpr in {iexpr1,iexpr2,...,iexprk}

    iexpr等都是整数表达式。

     

    SEQ的时序 

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

    我们也将随机访问存储器(寄存器文件、指令存储器和数据存储器)看成和组合逻辑一样的操作。(随机访问存储器需要等待高电平)

    由于指令存储器只用来读指令,因此我们可以将这个单元看成是组合逻辑。(内存向指令存储器中写指令是CPU外部的事件 不属于CPU内的时序)

    每个时钟周期,程序计数器都会装载新的指令地址。

    只有在执行整数运算指令时,才会装载条件码寄存器。

    只有在执行mov、push、call指令时,才会写数据存储器。

    要控制处理器中活动的时序,只需要寄存器和存储器的时钟控制

    因为指令运行计算的结果,写入寄存器存储器中。

    我们可以把取指、译码、执行等过程看做是组合逻辑的处理过程(因为它们不涉及写入寄存器)。把写回看做是另一个过程。

    则整个过程可简化为下图所示:

    举例详解

    有如下指令:

    0x000 : irmovl  $0x100, %ebx

    0x006 : irmovl  $0x200, %edx

    0x00c : addl    %edx, %ebx

    0x00e : je  dest

    0x013 : rmmovl  %ebx, 0(%edx)

    0x019 : dest: halt

    在我们的SEQ处理器中,一个时钟周期(即两次高电平时间的时间间隔)执行一条指令。

     

    时钟周期3开始时(点1处),一个高电平打入,地址0x00c载入程序计数器PC中。这样,与PC相连的MCU(主存控制单元)就在内存中把地址0x00c处的addl指令提取出来,加载到指令存储器中。(从内存中读取数据很慢,这个过程会很久,所以我们的时钟周期要很长,才能做到一个时钟周期执行一条指令)同时,PC的值加上addl指令的长度,得出新PC值,新PC值通过总线传播,等待下次高电平时写入PC。

    组合逻辑指令存储器中的输入一变化,值(addl指令)就通过逻辑门网络传播。故,瞬间读出了寄存器文件中%edx、%ebx的值(因为读寄存器文件不需要高电平触发)

    读出的%edx、%ebx的值瞬间流动到组合逻辑ALU中,ALU根据之前传播的addl指令,知道此为加法指令,瞬间计算出这两个值的结果valE。valE通过总线传播瞬间到达寄存器文件,但是此时还不能向寄存器文件写入,必须等待下次的高电平。

    故此时,寄存器文件和存储器中保存的还都是上条指令的结果值。(点1、2处)

    时钟周期4开始时(点3处),一个高电平打入,上周期产生的新PC值写入程序计数器,上周期计算得到的addl的结果valE值写入寄存器文件中的%ebx中。

    因为地址0x00e载入了程序计数器中,故会取出并执行跳转指令je。因为条件码ZF为0,所以不会选择分支。在这个周期末尾(点4),程序计数器已经产生了新值0x013。但是直到下个周期开始之前,寄存器和存储器中的状态还是保持着addl指令设置的值。

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

    读操作沿着这些单元传播,就好像它们是组合逻辑,而写操作是由时钟控制的。

    参考资料:http://blog.csdn.net/yang_yulei/article/details/22529437

                  http://www.tuicool.com/articles/Zv6v6n

                  http://www.cnblogs.com/20135202yjx/p/4888820.html

    实验:

    代码如下

  • 相关阅读:
    算法练习:求字符串的最长重复子串(Java实现)
    Oracle数据库中遇到的坑
    解决Oracle死锁问题步骤
    转:Spring Cache抽象详解
    Spring MVC测试框架详解——服务端测试
    转:SpringMVC中日期格式的转换
    freemarker判断是否为空
    jQuery Pagination分页插件
    Java链式方法
    mysql强制索引和禁止某个索引
  • 原文地址:https://www.cnblogs.com/huyufeng/p/4887815.html
Copyright © 2020-2023  润新知