ARM流水线

来源:互联网 发布:seo工资待遇 2017 编辑:程序博客网 时间:2024/04/28 01:17

 前言

 

  写这篇文章主要是做个笔记,写点心得。但写完这篇文章也不知道取个什么名字,索性就叫ARM流水线吧, 其内容主要是讲ARM流水线中,并于发生分支和跳转、异常等这类冒险时,流水线的一个执行流程和实时的PC值。

 

ARM 流水线

流水线是 RISC 执行指令时采用的一种机制,关于它的原理和概念就不多讲了。

在这里,我们称讨论以下几个内容:

一、流水线深度(级数)增加所带来的影响。

ARM7 采用 3 级流水线, ARM9 采用 5 线流水线, ARM10 采用 6 级流水线, 但是随着流水线深度的增加,指令的吞吐量提高了,每一段的工作量被消减了,使得处理器可以工作在更高的频率,同时也改善了性能,但系统延时 (latency) 也增加了,这是因为在内核执行一条指令前,需要更多的周期来填充流水线。并且,时钟频率的增加,指令执行周期也相应缩减了,这就要求减小指令执行周期的时间,也就对硬件设计带来了更大的要求。所以,流水线深度并不是越深越好。

二、流水线执行特点

         ARM 流水线的一条指令只有在完全通过 执行 阶段才被处理 。这句话很重要,也就是说,当处理器开始取第四条指令时,第一条指令才完成执行。我们如果不考虑流水线的设计,只看它的原理,其实是很简单的,他的复杂之处在于发生流水线冒险时,如何保证其工作得仍然很好。

         流水线冒险一般分为控制冒险和数据冒险,而数据冒险一般可分为阻塞 ( 即下一条指令依赖于前一条指令的结果 ) 、分支和跳转、异常(异常和中断)。由于 ARM 是硬件 flush 流水设计的,当发生冒险时,会暂停取指,然后清流水, (MIPS 解决冒险通常依赖于编译器,比如插入一条 NOP 指令及重新排列指令序列 )

         这里我们再结合 PC 的值的情况来分析一下流水线的工作原理。 PC :程序计数器,之所以重提这个概念,是因为我们需要理解 PC 的本来用意。在所有的流水线体系结构中, PC 总是指向当前正在执行的指令的地址加 8 字节的地址,换句话说, PC 总是指向当前正在执行的指令再加 2 条指令的地址。再换句通俗点的话来说, PC 就是当程序处于指令执行阶段的时候的那个值。在流水线的体系结构中,理解这一点是非常重要的。原因我们接着分析。

         假设我们的程序运行在最理想的情况下,不会发生任何的流水线冒险,程序顺序执行直到终止。此时,关于上面的这个概念(指 PC 指向执行阶段的指令的地址加 8 字节的地址)也就没有实际性的意义。但是,如果我们考虑进流水线冒险的情况,比如,有这样一组指令序列 S1 S2 S3 S4 S5 分别对应从第一条到第五条指令,如果在 S1 过程中,发生了一个 IRQ 的中断,那么,程序就打破了原先顺序执行的状态,需要跳转到中断向量表去处理相应的中断服务程序,然而,当处理器处理完中断之后,又不得不再回来原来发生中断的地方继续往下执行 S2 及以后的指令,为了确保这个过程能正常工作,我们就需要一个寄存器来保存中断返回时的地址正好是 S2 的地址,以便于处理器能正确的取出 S2 的指令。(在 ARM 中,通常用 lr r14 :程序链接寄存器)来保存程序的返回值,并且保存的动作由硬件来自动完成。)

         那么,我们现在的问题是,如何来确定 lr 的值是多少呢?这里,我们就要借助于 PC 的值了,如果我们知道当发生 IRQ 时, PC 的值是多少,那我们就可推算出 lr 的值。虽然我们上面给出了, PC 的值是 S1+8 的地址。尽管在 ARM 中, PC 的值和 LR 的值已经同硬件完成了,但我们也还是有必要知道它为什么就是 S1+8 的地址?

         当初在这个问题上,我也一下没有绕过来,为什么要规定 PC 是正在执行的指令的地址加 8 呢,试想一下,如果是一个五级流水的情况,如果 IRQ 发生在执行阶段之前,或者发生在访存阶段,那些时 PC 的值就应该是 PC+4 或者 PC+12 了啊,因为它此时处于 S2 取指或者 S4 取指阶段啊,呵呵,不知道有没有人刚开始的时候也有过类似的疑问啊?

         为了解释上面的这个问题,我们需要澄清一些原理的东西,也说明当初看书的时候并不仔细,理解得也不深,有点走马观花的味道,大忌啊!

         我们接着看 S1 发生中断是的情形,我们假设当处理器从 S1 取指阶段时就发生了 IRQ 中断,但此时却不会去响应 IRQ 中断,因为此时还不能确定中断入口向量表的地址,准确的说,此时 PC 的值还不是中断入口的地址,要确定中断入口的地址,必须等到执行阶段,处理器检测到有一个中断,并通过 ALU 计算而得到中断的入口地址,然后再写入 PC 中,实现跳转到中断入口处,也就是在写入这个值到 PC 并进行跳转之前,硬件自动保存了原来的那个 PC 值到 lr 中。因为中断的检测和中断入口的地址是在执行阶段时确定的,所以此时 PC 的值是 S1+8 的地址,或者是 S3 的地址。

         另外还要注意的就是,如果 S1 不是像 ADD R0 R1,R2 这样的指令而是访存指令的时候,处理器必须等到执行完访存之后,才会进入中断,而此时,流水线暂停取指并清空 S1 之后的所有位于流水线中的指令序列,这里是 S2 S3

         其它的像分支和跳转等冒险情况,也正是因为分支和跳转的地址是在执行阶段时确定的,所以 PC 的值也为处于执行阶段的指令地址加 8 的地址。这本是一个很简单的问题,但由于看书和理解不仔细,所以引发上面这么多的文字,

         再简要说下分支或者异常时返回时的地址: lr lr=S1+8 ,我想应该能明白了吧,也就是发生分支或者异常时的 PC 的值。

         像分支和跳转这类指令,分支返回之后,从 S2 开始执行,所以在进入分支后的代码中,有些需要显式的保存分支的返回值   SUB lr,lr,#4, 然后通过   MOV pc,lr 实现返回,有些可以通过像 BL 这样的指令来自动执行这两个过程。

         像异常这指令,返回地址又各有不同,下面给一个异常返回地址的表:

 

 

 

其原由,根据不同异常的具体情况分析一下就能明白,这里就不多说了。

 

原创粉丝点击