将处理组织成阶段

为了实现流水线处理机制,要将指令组织成某个特殊的阶段序列,所有的指令遵循统一的序列,不同阶段放在不同硬件上进行处理。下面是对各阶段的简述。

取指(fetch):取指阶段从内存读取指令字节,地址为程序计数器(PC)的值。从指令中抽取出指令指示符字节的两个四位部分,称为icode(指令代码)和ifun(指令功能)。它可能取出一个寄存器指示符字节,指明一个或两个寄存器操作数指示符rA和rB。它还可能取出一个四字节常数字va1C。它按顺序方式计算当前指令的下一条指令的地址va1P。也就是说,valP等于PC的值加上已取出指令的长度。

译码(decode):译码阶段从寄存器文件读入最多两个操作数,得到值valA和/或valB。通常,它读入指令rA和rB字段指明的寄存器,不过有些指令是读寄存器rsp的。

执行(execute):在执行阶段,算术/逻辑单元(ALU)要么执行指令指明的操作(根据ifun的值),计算内存引用的有效地址,要么增加或减少栈指针。得到的值我们称为valE。在此,也可能设置条件码。对一条条件传送指令来说,这个阶段会检验条件码和传送条件(由ifun给出),如果条件成立,则更新目标寄存器。同样,对一条跳转指令来说,这个阶段会决定是不是应该选择分支。

访存(memory):访存阶段可以将数据写入内存,或者从内存读出数据。读出的值为valM。

写回(write back):写回阶段最多可以写两个结果到寄存器文件。

更新PC(PC update):将PC设置成下一条指令的地址。

SEQ硬件结构

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

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

执行:执行阶段会根据指令的类型,将算术/逻辑单元(ALU)用于不同的目的。对整数操作,它要执行指令所指定的运算。对其他指令,它会作为一个加法器来计算增加或减少栈指针,或者计算有效地址,或者只是简单地加0,将一个输入传递到输出。条件码寄存器(CC)有三个条件码位。ALU负责计算条件码的新值。当执行条件传送指令时,根据条件码和传送条件来计算决定是否更新目标寄存器。同样,当执行一条跳转指令时,会根据条件码和跳转类型来计算分支信号Cnd。

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

写回:寄存器文件有两个写端口。端口E用来写ALU计算出来的值,而端口M用来写从数据内存中读出的值。

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

SEQ的时序

SEQ的实现包括组合逻辑和两种存储器设备:时钟寄存器(程序计数器和条件码寄存器),随机访问存储器(寄存器文件、指令内存和数据内存)。组合逻辑不需要任何时序或控制——只要输入变化了,值就通过逻辑门网络传播。正如提到过的那样,我们也将读随机访问存储器看成和组合逻辑一样的操作,根据地址输入产生输出字。对于较小的存储器来说(例如寄存器文件),这是一个合理的假设,而对于较大的电路来说,可以用特殊的时钟电路来模拟这个效果。由于指令内存只用来读指令,因此我们可以将这个单元看成是组合逻辑。

现在还剩四个硬件单元需要对它们的时序进行明确的控制——程序计数器、条件码寄存器、数据内存和寄存器文件。这些单元通过一个时钟信号来控制,它触发将新值装载到寄存器以及将值写到随机访问存储器。每个时钟周期,程序计数器都会装载新的指令地址。只有在执行整数运算指令时,才会装载条件码寄存器。只有在执行rmmovq、 pushq或cal1指令时,才会写数据内存。寄存器文件的两个写端口允许每个时钟周期更新两个程序寄存器,不过我们可以用特殊的寄存器IDOxF作为端口地址,来表明在此端口不应该执行写操作。

SEQ的实现

取指阶段:

取指阶段包括指令内存硬件单元。以PC作为第一个字节(字节0)的地址,这个单元一次从内存读出10个字节。第一个字节被解释成指令字节,(标号为“Split”的单元)分为两个4位的数。然后,标号为“icode”和“ifun”的控制逻辑块计算指令和功能码,或者使之等于从内存读出的值,或者当指令地址不合法时(由信号imem error指明),使这些值对应于nop指令。根据icode的值,我们可以计算三个一位的信号(用虚线表示)。从指令内存中读出的剩下9个字节是寄存器指示符字节和常数字的组合编码。标号为“Align”的硬件单元会处理这些字节,将它们放入寄存器字段和常数字中。当被计算出的信号need_regids为1时,字节1被分开装入寄存器指示符rA和rB中。否则,这两个字段会被设为OxF(RNONE),表明这条指令没有指明寄存器。任何只有一个寄存器操作数的指令,寄存器指示值字节的另一个字段都设为OxF(RNONE)。因此,可以将信号rA和rB看成,要么放着我们想要访问的寄存器,要么表明不需要访问任何寄存器。这个标号为“Align”的单元还产生常数字valC。根据信号need_regids的值,要么根据字节1~8来产生va1C,要么根据字节2~9来产生。

PC增加器硬件单元根据当前的PC以及两个信号need_regids和need_valc的值,产生信号valP。对于PC值p、need_regids值r以及need_va1c值i,增加器产生值p+1+r+8i。

译码和写回阶段:

寄存器文件有四个端口。它支持同时进行两个读(在端口AB上)和两个写(在端口E和M上)。每个端口都有一个地址连接和一个数据连接,地址连接是一个寄存器ID,而数据连接是一组64根线路,既可以作为寄存器文件的输出字(对读端口来说),也可以作为它的输入字(对写端口来说)。两个读端口的地址输入为srcA和srcB,而两个写端口的地址输入为dstE和dstM。如果某个地址端口上的值为特殊标识符OxF(RNONE),则表明不需要访问寄存器。

根据指令代码icode以及寄存器指示值rA和rB,可能还会根据执行阶段计算出的Cnd条件信号。

执行阶段:

执行阶段包括算术/逻辑单元(ALU)。这个单元根据alufun信号的设置,对输入aluA和aluB执行ADD、SUBTRACT、AND或EXCLUSIVE-OR运算。如图4-29所示,这些数据和控制信号是由三个控制块产生的。ALU的输出就是valE信号。执行阶段的第一步就是每条指令的ALU计算。列出的操作数 aluB在前面,后面是aluA,这样是为了保证subq指令是va1B减去valA。可以看到,根据指令的类型,alua的值可以是valA、valC,或者是一8或+8。

访存阶段:

访存阶段的任务就是读或者写程序数据。如图所示,两个控制块产生内存地址和内存输入数据(为写操作)的值。另外两个块产生表明应该执行读操作还是写操作的控制信号。当执行读操作时,数据内存产生值valM。

访存阶段最后的功能是根据取值阶段产生的icode、imem_error、instr_valid值以及数据内存产生的dmem error信号,从指令执行的结果来计算状态码Stat。

更新PC阶段:

SEQ中最后一个阶段会产生程序计数器的新值。如图 最后步骤所示,依据指令的类型和是否要选择分支,新的PC可能是valC、valM或valP。

3.3 Y86-64的顺序实现的更多相关文章

  1. Spring IOC 低级容器解析

    1.IOC是什么 IOC-Inversion of Control,即"控制反转",不是什么技术,而是一种设计思想.在Java开发中,Ioc意味着将你设计好的对象交给容器控制,而不 ...

  2. wamp安装失败原因大全

    wamp 是 Windos.Apache.Mysql.PHP集成安装环境 为了安装hdwiki 所以需要这个环境 1.下载wampserver_x86_3.0.6 64位  环境包,安装路径禁止有空格 ...

  3. 源码编译搭建LAMP

    环境版本信息: RHEL 5.3 Apache / 2.4.16 PHP / 5.4.45 mysql-5.5.45 源代码编译 安装方式 1: configure 配置 以及定制我们的软件包 2: ...

  4. MIT 操作系统实验 MIT JOS lab1

    JOS lab1 首先向MIT还有K&R致敬! 没有非常好的开源环境我不可能拿到这么好的东西. 向每个与我一起交流讨论的programmer致谢!没有道友一起死磕.我也可能会中途放弃. 跟丫死 ...

  5. 《Spring技术内幕》笔记-第二章 IoC容器的实现

    简单介绍 1,在Spring中,SpringIoC提供了一个主要的JavaBean容器.通过IoC模式管理依赖关系.并通过依赖注入和AOP切面增强了为JavaBean这样子的POJO提供事务管理,生命 ...

  6. Java内存模型深度解析:顺序一致性--转

    原文地址:http://www.codeceo.com/article/java-memory-3.html 数据竞争与顺序一致性保证 当程序未正确同步时,就会存在数据竞争.java内存模型规范对数据 ...

  7. sqlalchemy mark-deleted 和 python 多继承下的方法解析顺序 MRO

    sqlalchemy mark-deleted 和 python 多继承下的方法解析顺序 MRO 今天在弄一个 sqlalchemy 的数据库基类的时候,遇到了跟多继承相关的一个小问题,因此顺便看了一 ...

  8. 64位windows 7下成功配置TortoiseGit使用Github服务器

    最近感觉自己电脑上的代码太乱了,东一块.西一块……于是决定使用正规的源代码管理软件来管理自己以后写的代码.以前做小项目的时候用过TortoiseSVN,感觉不错,但是速度上有点慢,于是决定尝试一下新东 ...

  9. java内存模型-顺序一致性

    数据竞争与顺序一致性保证 当程序未正确同步时,就会存在数据竞争.java 内存模型规范对数据竞争的定义如下: 在一个线程中写一个变量, 在另一个线程读同一个变量, 而且写和读没有通过同步来排序. 当代 ...

  10. MDX函数(官方顺序,带示例)

    MDX函数(官方顺序) 1.  AddCalculatedMembers (MDX) 返回通过将计算成员添加到指定集而生成的集. 语法: AddCalculatedMembers(Set_Expres ...

随机推荐

  1. cpu的各种信息查询

    Linux查看物理CPU个数.核数.逻辑CPU个数 # 总核数 = 物理CPU个数 X 每颗物理CPU的核数 # 总逻辑CPU数 = 物理CPU个数 X 每颗物理CPU的核数 X 超线程数 # 查看物 ...

  2. ChannelInboundHandlerAdapter 类

    在 ChannelInboundHandlerAdapter 类中,除了 channelActive 和 channelRead 方法之外,还有其他方法用于处理不同类型的入站事件.以下是这些方法的解释 ...

  3. Java RMI遇到的Connection refused to Host: 127.x.x.x/192.x.x.x/10.x.x.x问题解决方法

    问题故障解决记录 -- Java RMI Connection refused to host: x.x.x.x .... 在学习JavaRMI时,我遇到了以下情况 问题原因:可能大家的host是10 ...

  4. java 执行 javascript 代码

    package com.ruoyi.project.front.controller; import java.math.BigDecimal; import java.util.*; import ...

  5. Redis知识网络

    Redis知识网络 作者:运维君莫笑 链接:https://www.zhihu.com/question/470465324/answer/2006650219 Redis为什么这么快? 根据官方数据 ...

  6. 动态类型语言 VS 静态类型语言

    一. 运行期动态修改类型结构 动态编程语言是高级编程语言的一个类别,在计算机科学领域已被广泛应用.它是一类在运行时可以改变其结构的语言:例如新的函数.对象.甚至代码可以被引进,已有的函数可以被删除或是 ...

  7. ChatGPT还是有点东西的-public static <T> List<T> Arrays.asList(T... a) {...}

    背景 业务开发需要判断业务状态是否在30.40.50.60的集合内,所以写了以下代码 int[] inLiq = {30,40,50,60}; return Arrays.asList(inLiq). ...

  8. CMake 进行多项目中dll的编译和链接

    前言(maybe废话) 最近正在学习cherno的游戏引擎教程,他使用的是vs进行构建的,后面换了premake.而我用的是vscode+cmake,所以在构建整个项目的时候踩了不少的坑,也找了很多资 ...

  9. 『手撕Vue-CLI』获取下载目录

    开篇 在上一篇文章中,简单的对 Nue-CLI 的代码通过函数柯里化优化了一下,这一次来实现一个获取下载目录的功能. 背景 在 Nue-CLI 中,我现在实现的是 create 指令,这个指令本质就是 ...

  10. 面试官:说说Netty对象池的实现原理?

    Netty 作为一个高性能的网络通讯框架,它内置了很多恰夺天工的设计,目的都是为了将网络通讯的性能做到极致,其中「对象池技术」也是实现这一目标的重要技术. 1.什么是对象池技术? 对象池技术是一种重用 ...