【【萌新的Risc-V学习之再看读不懂的流水线设计-10】】

news2024/11/26 20:42:01

萌新的Risc-V学习之再看读不懂的流水线设计-10

我们将流水线和之前案例中洗衣服的例子进行对照
我们把整个流水线分为5个阶段
也就是做成五级流水线

  1. IF: 取指令
  2. ID: 指令译码和读寄存器堆
  3. EX: 执行或计算地址
  4. MEM: 数据存储器访问
  5. WB: 写回
    在这里插入图片描述
    我先在这里表述一下基本的几个指令的用法

    add x1 x2 x3
    R型指令
    R[rd] = R[rn] +R [rm]
    1.取出指令, PC 自增。
    2.从寄存器堆读出两个寄存器 x2 x3, 同时主控制单元在此步骤计算控制信号。
    3.根据部分操作码确定 ALU 的功能,对从寄存器堆读出的数据进行操作。
    4.将 ALU 的结果写入寄存器堆中的目标寄存器 (x1)


现在介绍一下ld 的用法
R[rt] = M [ R[rn] + DATAaddr ]
ld x1 , offset(x2)
1.从指令存储器中取出指令, PC 自增。
2.从寄存器堆读出寄存器 (x2) 的值。
3.ALU 将从寄存器堆中读出的值和符号扩展后的指令中的 12 位(偏移量)相加。
4.将 ALU 的结果用作数据存储器的地址。
5.将从存储器读出的数据写入寄存器堆 (X 1)

《计算机组成原理》对流水线的刻画来说会有以下安排
IM 表示指令寄存器和取值阶段的 PC, Reg表示指令译码/寄存器读取阶段 (ID) 的寄存器堆和符号扩展单元,等等。为了保持正确的时序,这种形式化的数据通路将寄存器堆划分成两个逻辑部分:寄存器读取阶段 (ID) 的寄存器读和写回 (WB) 阶段的寄存器写。这种复用被表示为:在 ID 阶段,当寄存器堆没有被写入时,使用虚线绘制未被着色的寄存器堆的左半部分;在 WB 阶段,当寄存器堆没有被读取时,使用虚线绘制未被着色的寄存器堆的右半部分。与前文一致,我们假设寄存器堆是在时钟周期的前半部分写入的,在时钟周期的后半部分被读取
总是来说 前半部分是写 后半部分是读取
在这里插入图片描述
我们一步步来分析 既然想要对功能进行复用 那么一定要把数据进行适当的存储 我们需要在两项之间增加一个寄存器把数据存储下来
寄存器的名称由两个被该寄存器分开的阶段的名称来命名。例如, IF ID 阶段之间的流水线寄存器被命名为 IF/ID
在这里插入图片描述
IF/ID 寄存器的位宽必须为 96 位,因为它需要同时存储从存储器中提取出的 32 位指令以及自增的 64 PC 地址。我们将在本章中逐渐增加这些寄存器的位宽,不过目前,其他三个流水线寄存器的位宽分别为 256 位、193 位和 128位
在这里插入图片描述
其他都还好说 这里有一段 对STUR的 研究
EX: 存储指令在流水线中的第三个阶段。不同千图 4-35 中加载指令的第三个流水阶段,第二个寄存器中的值被加载到 EX/MEM 流水线寄存器中以用千下一个阶段。尽管总是将第二个寄存器中的值写入 EX/MEM 流水线寄存器中不会造成任何影响,但为了使流水线更容易被理解,我们仅在存储指令中写第二个寄存器中的值
这里说的是 M [ R[Rn] + DTAaddr ] = R [ Rt ]
这个意思说的是 我们先读取到的Rt 的内容 然后 存放在 ID/EX 接下来 存下来 会继续存到 EX/MEM中去
在这里插入图片描述
大概都理解了 让我们去看一下最后总结一下
在这里插入图片描述
在这里插入图片描述
下面讲述的是一个大体上的对控制信号的排布 其实并不重要
因为他对单周期的改造和我自己写的单周期并不相同

1.取指:读指令存储器和写 PC 的控制信号总是有效的,因此在这个阶段没有什么需要特别控制的内容。
2.指令译码/读寄存器堆:在 RISC-V 指令格式中两个源寄存器总是位于相同的位置,因此在这个阶段也没有什么需要特别控制的内容。
3.执行/地址计算:要设置的信号是 ALUOp和 ALUSrc , 这个信号选择 ALU 操作,并将读数据 或者符号扩展的立即数作为 ALU 的输入。
4.存储器访问:本阶段要设置的控制线是 Branch MemRead MemWrite 。这些信号分别由相等则分支、加载和存储指令设置。除非控制电路标示这是一条分支指令并且 ALU的输出为 0, 否则将选择线性地址的下一条指令作为 PCSrc 信号。
5. 写回:两条控制线是 MemtoReg和 RegWrite, Mem oReg决定是将 ALU 结果还是将存储器值发送到寄存器堆中, Re Writ 写入所选值。
EX阶段的两个操作是 ALUop ALUSrc
M阶段的三个操作是 Branch MemRead MemWrite
WB阶段的两个操作是 MentoReg RegWrite
在这里插入图片描述
在这里插入图片描述
虽然我大概懂了 但是我觉得毫无意义

往下推论
我们并不是一定要在最后Datamemory 阶段传递数据的 我们每次在寄存器运算完成后都可以把数据存下来以备后续的使用

下面是讲述的包含前递之后的整个电路图
在这里插入图片描述
okok我们在这里先做一个总结
从一开始拿到数据 那先讲control信号 控制信号进行分段 每段传递一个功能 用完就丢弃
然而数据也是这样的 传递过去一个部门只执行一项东西 因为是流水线嘛
所以我们对于control信号 可以分开执行
在这里插入图片描述
控制信号说完之后 我们讲述 数据通路的运转
数据通路 我们 在传递中意识到了并不是一定要等到结算完成之后才读取
我们可以在寄存器中读取数据
这就引出了前递的概念
当然我们上面介绍是关于R型指令的前递
我大概明白上面的意思
从表格上我们可以看出数据主要可以来自三个大方向
1.寄存器堆 (自己提取)
2.ALU计算结果 (maybe 是 需要R型的结果)
3.datamemory (maybe is used at ld or sd)
在这个结尾 它补充了一段 说是立即数没考虑进去最后加了一个新的立即数选择模块
在这里插入图片描述
ok 总结完毕 我们接下来看的是 非R型指令
这里面有一个什么问题呢
在这里插入图片描述
我们观察可知
因为我们所使用各项数据 基本上都是在ALU阶段
我们不去管这条指令是啥 主要在于他是否用到了上一条指令
我们观察上一条指令是R型那么我们在ALU刚计算完就可以直接拿数据了
但是如果上一条是LD或者SD 那么最终数据的取值 会在datamemory中
这里又会有数据位的参差 其实相对来说差了一整个时钟周期
所以对我们来说 我们的解决方法是增加一个检测单元
从而可以在加载指令和相关加载指令结果的指令之间加入一个流水线阻塞。
回想一下,我们在加载指令和 型指令中使用 Regi erRd 也就是指令的 11(11 :7) 表示指定的寄存器。第一行测试是为了查看指令是否是加载指令:只有加载指令需要读取数据存储器。接下来的两行检测在 EX 阶段的加载指令的目标寄存器是否与 ID 阶段的指令中的某一个源寄存器相匹配。如果条件成立,指令会停顿一个时钟周期。在一个时钟周期后,前递逻辑就可以处理这个相关并继续执行程序了。(如果没有前递,那么图 4-56 中的指令还需要再停顿一个时钟周期。)

接下来说一下 这个暂停是怎么做的
如果处于 ID 阶段的指令被停顿了,那么在 IF 阶段中的指令也一定要被停顿,否则已经取到的指令就会丢失。只需要简单地禁止 PC 寄存器和 IF/ID 流水线寄存器的改变就可以阻止这两条指令的执行。·
在这里插入图片描述
因为我们需要的是正确的ALU的输入 而对我们来说 停顿一个时钟周期
因为ALU不执行操作 那么 前面的阶段也不能执行
ID IF 两个阶段的操作需要停止
不更新新的值 那么是否会继续使用原本的老的值呢。如果这些寄存器被保护,在 IF 阶段的指令就会继续使用相同的 PC取指令,同时在 ID 阶段的寄存器就会继续使用 IF/ID 流水线寄存器中相同的字段读寄存器。
如何在流水线中插入空指令(就像气泡那样)呢?从图 4-47 中可知,解除 EX MEMWB 阶段的七个控制信号(将它们设置为 0) 就可以产生一个“没有任何操作”的指令,也就是空指令。通过识别 ID 阶段的冒险,我们可以通过将 ID/EX 流水线寄存器中 EX MEMWB 的控制字段设置为 来向流水线中插入一个气泡。这些不会产生负面作用的控制值在每个时钟周期向前传递并产生适当的效果:在控制值均为 的情况下,不会有寄存器或者存储器被写入数据。
and 指令所在的流水线执行槽变成了 no p指令,并且所有在 and 指令之后的指令都被延后了一个时钟周期。就像水管中出现了一个气泡那样,这个停顿气泡延后了它之后的所有指令的执行,并且随着每个时钟周期沿着流水线继续前进,直到其退出流水线。在本例中,这个冒险使得 and 指令和 or 指令在第 个时钟周期内重复了它们在第 个时钟周期内做过的事情: and 指令读寄存器和解码, or 指令从指令存储器中重新取了一遍指令。这种重复看起来就像是停顿一样,它的影响是拉伸了 and令和 or 指令,并且延后了取第 and 指令的时间。
在这里插入图片描述
在流水线中插入停顿的方法。通过将 and 指令替换成 no p,在第 个时钟周期中插入了一个停顿。需要注意的是 and 指令在第 和第 个时钟周期内被译码和解码,但它的 EX 阶段被延后到第 个时钟周期中(如果没有停顿, EX 阶段应该发生在第 个时钟周期中。)相应的,or 指令在第 个时钟周期被译码,但它的 ID 阶段被延后到第 个时钟周期中(如果没有停顿, ID 阶段应该发生在第 个时钟周期中。)在插入气泡后,所有的相关性沿着时间轴继续向前,但是不会再发生冒险了
在这里插入图片描述
图中高亮显示了流水线中冒险检测单元和前递单元之间的连接。和原来一样,前递单元控制 ALU 多选器,用相应的流水线寄存器中的值替换通用寄存器中的值。冒险检测单元控制 PC IF/ID 流水线寄存器的写入,以及在实际控制值和全 之间选择的多选器。如果加载-使用冒险被检测为真,则冒险检测单元会停顿并清除所有控制字段。

我们现在分析控制冒险
迄今为止,我们只将对冒险的关注局限在算术操作和数据传输中。然而,正如 4.5 节所示,流水线冒险也包括条件分支。画出了一个指令序列,并标明在这个流水线中分支是何时发生的。每个时钟周期都必须进行取值操作以维持流水线,不过在我们的设计中,要等到 MEM 流水线阶段才可以决定分支是否发生。正如 4.5节中所述,这种为了决定正确执行指令所产生的延迟被称为控制冒险或分支冒险,这与我们之前讨论的数据冒险相对应。
在这里插入图片描述
分支指令对流水线的影响。指令左边的数字 (40 44 等)代表指令的地址。因为分支指令在 MEM 阶段决定是否跳转(也就是图中 be q指令在第 个时钟周期内的操作),分支指令后续的三条指令都将被取值并且开始执行。如果不进行干预,这三条后续指令会在 beq指令跳转到地址 72 上的 指令之前就开始执行(图 4-29 使用了额外的硬件以减小控制冒险至一个时钟周期,而本图使用的是没有优化的数据通路。

我们这里说的分支指令在MEM阶段是从最上面的那个beq说起的 因为对我来说 我之前在写单周期的代码的时候 并没有放到MEM阶段 但是他在写代码的时候放到了MEM阶段

阻塞流水线直到分支完成的策略非常耗时。一种提升分支阻塞效率的方法是惊测条件分支不发生并持续执行顺序指令流。一旦条件分支发生,已经被读取和译码的指令就将被丢弃,流水线继续从分支目标处开始执行。如果条件分支不发生的概率是50%, 同时丢弃指令的代价又很小,那么这种优化方式可以减少一半由控制冒险带来的代价。想要丢弃指令,只需要将初始控制值变为 即可,这与指令停顿以解决加载-使用的据冒险类似。不同的是,丢弃指令的同时也需要改变当分支指令到达 MEM 阶段时 IF ID和EX阶段的三条指令,;而在加载-使用的数据停顿中,只需要将 ID 阶段的控制信号变为 并且将该阶段的指令从流水线中过滤出去即可。丢弃指令,意味着我们必须能够将流水线中 IF ID EX 阶段中的指令都清除。

困难的部分是分支决定本身。对于相等时跳转指令,需要在 ID 阶段比较两个寄存器中的值是否相等。相等的判断方法可以是先将相应位进行异或操作,再对结果按位进行或操作。将分支检测移动到 ID 阶段还需要额外的前递和冒险检测硬件,因为分支可能依赖还在流水线中的结果,在优化后依然要保证运行正确。例如,为了实现相等时跳转指令(或者不等时跳转指令),需要在 ID 阶段将结果前递给相等测试逻辑。这里存在两个复杂的因素:.在 ID 阶段需要将指令译码,决定是否需要将指令旁路至相等检测单元,并且完成相等测试以防指令是一条分支指令,此时可以将 PC 设置为分支目标地址。对分支指令的操作数进行前递的操作原先是由 ALU 前递逻辑处理的,但是在 ID 阶段引入相等检测单元后就需要添加新的前递逻辑。需要注意的是,旁路获得的分支指令的源操作数既可以从 EX/MEM流水线寄存器中获得,也可以从 MEM/WB 流水线寄存器中获得。.在 ID 阶段分支比较所需的值可能在之后才会产生,因此可能会产生数据冒险,所以指令停顿也是必需的。例如,如果一条 ALU 指令恰好在分支指令之前,并且这条 ALU 指令产生条件分支检测时所需的操作数,那么一次指令停顿就是必需的,因为 ALU 指令的 EX阶段将发生在分支指令的 ID 阶段之后。又例如,如果一条加载指令恰好在条件分支指令之后,并且条件分支指令依赖加载指令的结果,那么两个时钟周期的停顿就是必需的,因为加载指令的结果要在 MEM 阶段的最后才能产生,但是在分支指令的 ID 阶段的开始就需要了

总结一下 我们想把整个控制冒险浓缩到ID阶段解决
那么会带来许多的问题 因为IF/ID寄存器会提供指令的立即数字段 也会提供 PC的值
接下来 两个难点 一个是计算分支目标的地址 还有一个是判断分支条件
我们把指令发送给ID阶段后,ID阶段会确定是否传递至旁路检测单元
但是这个旁路检测单元需要传递很多信息给他 比如说来自两个ALU端的数据究竟在哪里 需要很多单元的前递去供养这个内容的加法
还有第二个问题 我们在ID阶段 那么其实相对来说比之前的EX还要早 那么 就像是加载指令一样来自于 MEM阶段的怎么办呢 是不是还有采取停顿的操作
尽管这很困难,但是将条件分支指令的执行移动到 ID 阶段的确是一个有效的优化,因为这将分支发生时的代价减轻至只有一条指令,也就是分支发生时正在取的那条指令,下面的例题展示了实现前递路径和检测冒险的更多实现细节。
为了清除 IF 阶段的指令,我们添加了一条称为 IF.Flush 的控制线,它将 IF/IF 流水线寄存器中的指令字段设置为 。将寄存器清空的结果是将已经取到的指令转换成一条 no p指令,该指令不进行任何操作,也不改变任何状态。

我们这里先介绍一下两张图片的对比差距
在这里插入图片描述
在这里插入图片描述发现ID阶段多了几个新的旁路设施用来进行计算
我们先讲述一下 这个基本的需要完成的代码的条数
36 sub x10, x4, x8
40 beq x1, x3,16 //PC-rela ti vebranch t o40+16*2=72
44 and x12, x2, x5
48 or x13, x2, x6
… …
72 ld x4, 50(x 7)

我们先来分析时刻三全状态的不同的意思

在这里插入图片描述
第四个时钟
在这里插入图片描述
在第 个时钟周期的 ID 阶段决定分支执行必须被执行,因此选择 72 作为下一 PC跳转地址,并且将下个时钟周期获取到的指令置 。第 个时钟周期显示了地址 72中的指令被获取,并且因为分支发生而在流水线中产生了一个气泡或者 nop指令

最终实现的流水线运行图
(它其实还说了一个可以存东西的最大流水线没精力看了 把这个搞完就好了)
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1056236.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

javaSwing销售管理

​ 目录 一、选题背景 近几年来,传统商业与电商似乎是水火不容,大有不是你死便是我活的劲头。一直以来舆论都是一边倒的电商将迅速取代传统零售的论调,然而几年过去,电商的发展确实值得侧目,但传统商业虽然受到不小的…

深入学习git

1、git原理及整体架构图 一些常用的命令 git add . 或 git add src/com/ygl/hello/hello.java 指定文件 git commit . 或 git commit src/com/ygl/hello/hello.java 指定文件 git push origin 分支名称 2、git stash的应用场景 场景一:你正在当前分支A开发&…

计算机操作系统 (王道考研)笔记(四)I/O系统

目录 1 I/O1.1 I/O 概念和分类1.1.1 I/O 定义1.1.2 I/O 分类 1.2 I/O控制器1.3 I/O 软件层次结构1.4 I/O 应用程序接口和驱动程序应用接口 1 I/O 1.1 I/O 概念和分类 1.1.1 I/O 定义 BIOS(英文:Basic Input/Output System),即基…

Redis主从复制、哨兵模式、群集部署

目录 一、Redis高可用 二、Redis主从复制 主从复制的作用 主从复制的流程 实例 三、Redis哨兵模式 哨兵的核心功能 哨兵模式的作用 哨兵结构的组成 故障转移机制 实例 四、Redis群集 集群的作用,可以归纳为两点: Redis集群的数据分片&#…

【Java开发】Redis位图轻松实现统计用户三日内留存数据

上一篇文章介绍了如何通过 Redis 位图实现统计日活周活月活,而 Redis 位图能做的远不止如此,本篇文章将介绍如何实现统计用户连续三日内登录的留存数据,从而更直观的反映软件的运营情况。 目录 1 实现思路 2 统计用户三日内留存数据 2.1 …

[AIGC] “惊天神器!Java大师推荐的终极工具 Netty ,让你的代码速度狂飙!“

前言: 在现代网络技术中,高性能的网络传输和通信已经成为了一项非常重要的技能。而Netty作为一款高性能、异步事件驱动的网络应用框架,成为了Java开发者们的首选工具之一。作为一位Java大师,今天我将从三个方面(是什么…

C++笔记之环形队列

C笔记之环形队列 code review! 文章目录 C笔记之环形队列1.概念I——摘自 https://mp.weixin.qq.com/s/HUn9TF09RZ-UJKYPR5ZXhA2.概念II——摘自 http://t.csdnimg.cn/72bng3.概念III—— 摘自https://mp.weixin.qq.com/s/9Ga502p1DLcc6o75JBQlDg4.概念IV—— 摘自https://mp…

Scala第十三章节

Scala第十三章节 1. 高阶函数介绍 2. 作为值的函数 3. 匿名函数 4. 柯里化 5. 闭包 6. 控制抽象 7. 案例: 计算器 scala总目录 文档资料下载

面试打底稿⑦ 项目一的第三部分

简历原文 抽查部分 完成路线规划模块选择路线功能,用neo4j这种存储图关系的非关系数据库,实现最短线路规划、最低成本线路规划 设计优化物流信息模块,合理选择数据库、缓存技术,实现数据精简、流量削峰、提高系统可 用性 模拟问答…

2023(2024届)计算机保研经验分享,圆梦山东大学

前言: Hello大家好,我是Dream,好久不见啦!在这不见的半年多时间里我一直在全身心的投入保研之中,在写下这份面经时,真的是感慨颇多,思绪万千。站在这个时间点上,回首过去的几个月&am…

汽车电子——产品标准规范汇总和梳理(控制器)

文章目录 前言 一、电机控制 二、转向控制 三、制动控制 四、电池管理系统 五、充电系统 六、车身系统 七、通讯系统 总结 前言 见《汽车电子——产品标准规范汇总和梳理》 一、电机控制 《GB/T 18488.1-201X 电动汽车用电机及其控制器 第1部分:技术条件…

数字IC前端学习笔记:数字乘法器的优化设计(阵列乘法器)

相关阅读 数字IC前端https://blog.csdn.net/weixin_45791458/category_12173698.html?spm1001.2014.3001.5482 数字信号处理作为微处理器的核心部件,是决定着总体处理器性能的因素之一,而数字乘法器是最常见的一种数字信号处理电路。通常情况下&#…

AMBA总线APB、AHB、AXI(详细)总结附实例便于快速掌握

目录 一、简介二、具体内容2.1 APB2.2 AHB2.3 AXI 三、总线对比3.1 总体对比3.2 部分功能差异 四、其他相关链接1、PCI总线及发展历程总结2、SPI协议详细总结附实例图文讲解通信过程3、I2C总线内容总结分享 一、简介 本文主要介绍APB、AHB和AXI总线的相关内容,同时…

初级篇—第一章初识数据库

文章目录 为什么要使用数据库数据库与数据库管理系统数据库的相关概念数据库与数据库管理系统的关系 常用的数据库为什么如此多的厂商要选用MySQL?MySQL的目录 RDBMS 与 非RDBMS关系型数据库(RDBMS)非关系型数据库(非RDBMS) 关系型数据库设计规则表、记录、字段表的…

力扣:117. 填充每个节点的下一个右侧节点指针 II(Python3)

题目: 给定一个二叉树: struct Node {int val;Node *left;Node *right;Node *next; } 填充它的每个 next 指针,让这个指针指向其下一个右侧节点。如果找不到下一个右侧节点,则将 next 指针设置为 NULL 。 初始状态下,所…

Springboot+vue的在线试题题库管理系统(有报告),Javaee项目,springboot vue前后端分离项目。

演示视频: Springbootvue的在线试题题库管理系统(有报告),Javaee项目,springboot vue前后端分离项目。 项目介绍: 本文设计了一个基于Springbootvue的前后端分离的在线试题题库管理系统,采用M&…

代码随想录算法训练营第五十二天 | 300. 最长递增子序列 674. 最长连续递增序列 718. 最长重复子数组

1. 最长递增子序列 300. 最长递增子序列 - 力扣(LeetCode) dp[i] 取决于 i 之前所有的dp class Solution {public int lengthOfLIS(int[] nums) {// dp[i] 第 0 - i 位的递增子序列长度int length nums.length;int[] dp new int[length];Arrays.fil…

基于 jasypt 实现spring boot 配置文件脱敏

前言 在项目构建过程中,保护敏感信息的安全性至关重要,为了提高系统的安全性能,我们采用了Jasypt来对配置文件中的敏感信息进行加密处理,以确保系统的机密信息不被轻易泄露。 步骤 添加Maven依赖 首先,我们需要添加…

秋招校招,什么是群面?

时间已经来到十月份,我们也迎来了秋季招聘的高峰期。一般来说,企业为了提高面试的速度,一般都会让我们进行群面。可是,很多人不懂得“群面”的意思,由此导致自己在面试环节丢分。今天,就跟着小编一起来了解…

Maven下载源码出现:Cannot download sources Sources not found for org.springframwork...

Maven下载源码出现:Cannot download sources Sources not found for org.springframwork… 最近重装了IDEA再次查看源码时发现总是报错,网上找了很多,发现解决方法都是在项目终端执行如下命令: mvn dependency:resolve -Dclassi…