我们按照整体的思路分段
将数据通路划分为5个阶段
IF : 取地址
ID :指令译码和读存储器堆
EX :执行或计算地址
MEM : 数据存储器访问
WB : 写回
单周期数据通路(与图 4-17 类似)。指令执行的每一步都从左至右地映射到数据通路中。唯一的例外是 PC 更新与写回的步骤(在图中用灰色表示),以上步骤发送 ALU 运算结果或存储中的数据到左侧,写入寄存器堆中(通常我们使用灰线表示控制,但在这里表示数据通路)
这五个部分与图中数据通路的绘制方式是对应的,指令和数据通常随着执行过程从左到右依次通过这五个阶段。再回到我们的洗衣类比,在通过工作线路时衣服依次被清洁、烘干和整理,同时永远不会逆向移动。然而,在从左到右的指令流动过程中存在两个特殊情况:·在写回阶段,它将结果写回位于数据通路中段的寄存器堆中。·在选择下- PC 值时,在自增 PC 值与 MEM 阶段的分支地址之间进行选择。从右到左的数据流向不会对当前的指令造成影响,这种反向的数据流动只会影响流水线中的后续指令。需要注意的是,第一种特殊情况会导致数据冒险,第二种会导致控制冒险。
IM 表示指令寄存器和取值阶段的 PC
Reg表示指令译码/寄存器读取阶段 (ID) 的寄存器堆和符号扩展单元,等等。
为了保持正确的时序,这种形式化的数据通路将寄存器堆划分成两个逻辑部分:寄存器读取阶段 (ID) 的寄存器读和写回 (WB) 阶段的寄存器写。这种复用被表示为:在 ID 阶段,当寄存器堆没有被写入时,使用虚线绘制未被着色的寄存器堆的左半部分;在 WB 阶段,当寄存器堆没有被读取时,使用虚线绘制未被着色的寄存器堆的右半部分。与前文一致,我们假设寄存器堆是在时钟周期的前半部分写入的,在时钟周期的后半部分被读取。
明三条指令需要三条数据通路,但事实上,我们可以通过引入寄存器保存数据的方式,使得部分数据通路可以在指令执行的过程中被共享。
指令存储器只在指令的五个阶段中的一个阶段被使用,而在其他四个阶段中允许被其他指令共享。为了保留在其他四个阶段中的指令的值,必须把从指令存储器中读取的数据保存在寄存器中。类似的理由适用于每个流水线阶段,所以我们必须将寄存器放置在图 中每个阶段之间的分隔线上。再回到洗衣例子中,我们会在每两个步骤之间放置一个篮子,用于存放为下一步所准备的衣服。
在图中用灰色表示的流水线寄存器将流水线的各阶段分开。它们被标记为被它们所分开的阶段,例如,第一个流水线寄存器被标记IF/ID, 因为它将取值和指令译码阶段分开。寄存器的位宽必须足够大以存储通过它们的所有数据。例如, IF/ID 寄存器的位宽必须为 96 位,因为它需要同时存储从存储器中提取出的 32 位指令以及自增的 64 PC 地址。我们将在本章中逐渐增加这些寄存器的位宽,不过目前,其他三个流水线寄存器的位宽分别为 256 位、193 位和 128位
需要注意的是,在写回阶段的最后没有流水线寄存器。所有的指令都必须更新处理器中的某些状态,如寄存器堆、存储器或 PC 等,因此,单独的流水线寄存器对于已经被更新的状态来说是多余的。例如,加载指令将它的结果放入 32 个寄存器中的一个,此后任何需要该数据的指令只需要简单地读取相应的寄存器即可。当然,每条指令都会更新 PC, 无论是通过自增还是通过将其设置为分支目标地址。 PC可以被看作一个流水线寄存器:它给流水线的 IF 阶段提供数据。不同于图 中被标记阴影的流水线寄存器, PC 是可见体系结构状态的一部分,在发生例外时, PC 中的内容必须被保存,而流水线寄存器中的内容则可以被丢弃。在洗衣的例子中,你可以将 PC 看作在清洗步骤之前盛放脏衣服的篮子。
为了详细展示流水线的主要功能运作方式 我们选取了一条使用5个阶段的指令
我们选择加载指令的load行为
当寄存器或存储器被读取时,我们高亮显示它们的右半部分;当它们被写入时,我们高亮显示它们的左半部分。
IF表示取指令
ID表示指令译码/读寄存器堆
。尽管在阶段二中加载指令只需要寄存器 中的值,但是处理器此时并不知道当前是哪一条指令正在被译码,因此处理器将符号扩展后的 16 位常撮以及两个寄存器中的值都存入 ID/EX 流水线寄存器中。我们并不一定需要全部的这三个操作数,但是保留全部三个操作数可以简化控制
第一部分: 取指令
顶端电路描绘了使用 PC 中的地址从存储器中读取指令,然后将指令放入IF/ID 流水线寄存器中。 PC 中的地址自增 4, 然后写回 PC, 以为下一时钟周期做准备。这个PC 值也保存在 IF/ID 流水线寄存器中,以备后续的指令使用(例如 be q)。计算机并不知道当前正在提取的是哪一种指令,因此它必须为任何一种指令做好准备,并且将所有可能有用的信息沿流水线传递出去。
第二部分 : 指令译码和读寄存器堆
底部显示了 IF/ID 流水线寄存器的指令部分,该指令提供一个 64 位符号扩展的立即数字段,以及两个将要读取的寄存器编号。所有这三个值都与 PC 地址一起存储在 ID/EX 流水线寄存器中。在这里我们再次向右传递在之后的时钟周期里指令可能用到的所有信息。
第三部分 : 执行或地址计算
显示了加载指令从 ID/EX 流水线寄存器中读取一个寄存器的值和一个符号扩展的立即数,并且使用 ALU 部件将它们相加,它们的和被存储在 EX/MEM 流水线寄存器中。
第四部分 : 存储器访问
部显示了加载指令使用来自 EX/MEM 流水线寄存器中的地址读取数据存储器,并将数据存入 MEM/WB 流水线寄存器中。
第五部分 : 写回
从 MEM/WB 流水线寄存器中读取数据,并将它写入图中间的寄存器堆中。
在介绍完加载指令之后 我们开始研究
存储指令的过程
1.取指 :使用 PC 中的地址从存储器中读取指令,然后将其放入 IF/ID 流水线寄存器中。该阶段发生在指令被识别之前,因此上述电路同时适用于加载和存储指令。
2.指令译码和读寄存器 : IF/ID 流水线寄存器中的指令提供了用于读取寄存器的两个寄存器编号以及一个符号扩展的立即数。这三个 64 位的值都存储在 ID/EX 流水线寄存器中。因为此时还不知道指令的类型,所以所有的指令都会执行这两个阶段.
3.指令执行和地址计算 : 有效地址被存放在EX/MEM流水线寄存器中
4 . 存储器访问:顶端显示了正在被写入存储器的数据。需要注意,包含要被存储的数据的寄存器在较早的流水线阶段就已经被读取并存储在 ID/EX 流水线寄存器中。在MEM 阶段获得这个数据的唯一方法就是在 EX 阶段中将该数据放入 EX/MEM 流水线寄存器中,就像我们将有效地址存储在 EX/MEM 中那样。
5.写回 :底端显示了存储指令的最后一步。对存储指令来说,在写回阶段不会发生任何事情。由于存储指令之后的每一条指令都已经进入流水线中,所以我们无法加速这些指令。因此,任何指令都要经过流水线中的每一个阶段,即使它在这个阶段没有任何事情要做,因为后续指令已经按照最大速率在流水线中进行处理了。
存储指令再次说明了如果要将相关信息从之前的流水线阶段传递到后续的流水线阶段,就必须将它们放置在流水线寄存器中。否则,当下一条指令进入流水线时,该信息就会丢失。对于存储指令来说,我们需要将在 ID 阶段读取的寄存器信息传递到 MEM 阶段,然后写入存储器中。这些数据最初放置在 ID/EX 流水线寄存器中,之后被传送到 EX/MEM 流水线寄存器中。其次,加载和存储指令还说明了第二个关键点:在流水线数据通路设计中的每一个逻辑部件(例如指令存储器、寄存器读端口、 ALU 、数据存储器、寄存器写端口等)只能在单个流水线阶段中被使用,否则就会发生结构冒险。因此,这些部件以及对它们的控制只能与一个流水线阶段相关联。
大体的整个流水线结构
流水线的图形化的分析
两种基本的流水线图
多时钟周期流水线图 稍微简单 和 单时钟周期流水线分析
我们以5条指令 为基础 组成序列
ld x10, 40(x1)
sub x11, x2, x3
add x12, x3, x4
ld x13, 48(x1)
add x14, x5, x6
下图是整个多周期的概念图