Skip to content

LV025-三级流水线

前边知道了 PC 的值 = 当前正在执行指令在内存中的地址 + 8 可是这是为什么呢?下边我们来简单了解一下。

img

从上图中我们看到 CPU 内部有 3 个主要组成部分:指令寄存器指令译码器指令执行单元(包括 ALU 和通用寄存器组)。 CPU 在执行 1 条指令的时候,主要有 3 个步骤:取指(将指令从内存或指令 cache 中取入指令寄存器);译码(指令译码器对指令寄存器中的指令进行译码操作,从而辨识出该指令是要执行 add,或是 sub,或是其它操作,从而产生各种时序控制信号);执行(指令执行单元根据译码的结果进行运算并保存结果) 。

现在我们假设一下:CPU 串行执行程序(即:执行完 1 条指令后,再执行下一条指令);指令执行的 3 个步骤中每个步骤都耗时 1 秒;整个程序共 10 条指令。那么,这个程序总的执行时间是多少呢?显然,是 30 秒。但这个结果令我们非常不满意,因为它太慢了。有没有办法让它座上京津高铁提速 3 倍呢?当然有!仔细观察上图,我们发现:取指阶段占用的 CPU 硬件是指令通路和指令寄存器;译码阶段占用的 CPU 硬件是指令译码器;执行阶段占用的 CPU 硬件是指令执行单元和数据通路。三者占用的 CPU 硬件完全不同,这样就使得如下的操作得以进行:在对第 1 条指令进行译码的时候,可以同时对第 2 条指令进行取指操作;在对第 1 条指令进行执行的时候,可以同时对第 2 条指令进行译码操作,对第 3 条指令进行取指操作。显然,这样就可以将该程序的运行总时间从 30 秒缩减为 12 秒,提速近 3 倍。上面所述并行运行指令的方式就被称为流水线操作。可见:流水线操作的本质是利用指令运行的不同阶段使用的 CPU 硬件互不相同,并发的运行多条指令,从而提高时间效率。

image-20230721213050544

流水线的引入,的确提高了 CPU 运行指令的时间效率,但却为我们的汇编程序编写引入了新的问题。为什么这么说?

寄存器 PC 的值是 即将被取指的指令的地址,正常情况下,在该条指令被取入 CPU 后执行期间,PC 的值保持不变,在该条指令执行完成的时间点上,硬件会自动将 PC 的值增加一个单位的大小,这样 PC 就指向了下一条将被取指和执行的指令。而在引入流水线后,PC 值的情况发生了变化,假定第 1 条指令的内存地址为 X:

在时刻 T,PC 的值变为 X,并在时刻 T 至时刻 T+1 期间维持不变;

在时刻 T+1,PC 的值变为 X+1 个单位,并在时刻 T+1 至时刻 T+2 期间维持不变;

在时刻 T+2,PC 的值变为 X+2 个单位,并在时刻 T+2 至时刻 T+3 期间维持不变;

在时刻 T+3,PC 的值将变为 X+3 个单位。

(PC 的值为什么一直在增加,因为要保证流水线正常工作就得不停取指,每次取值 PC 值当然增加,对照上图理解) 由此可见,在第 1 条指令的执行阶段,PC 的值不再是该指令在内存中的位置,而是该指令在内存中的位置+2 个单元。对于 ARM 指令集而言,每条指令的长度为 32bit,占 4byte,所以 1 条指令在内存中需要 4byte 存储。

因此,我们的结论是:指令执行时, PC 的值 = 当前正在执行指令在内存中的地址 + 8