- 指令周期Cycle1
- 取指
PC总是指向将要读取的指令的地址(即我们常说的,指向下一条指令的地址),而当前PC=4,
所以去取物理地址为4对对应的指令"A" 二进制代码为"A_BIT"
此处取指完之后,自动更新PC的值,即PC=PC+4(单个指令占4字节,所以加4)=4+4=8(pc=8)
- 取指
- 指令周期Cycle2
- 译指
翻译指令"A"
- 同时再去取指
PC总是指向将要读取的指令的地址(即我们常说的,指向下一条指令的地址),而当前PC=8,
所以去物理地址为8所对应的指令"B" 其对应二进制代码为"B_BIT"。
此处取指完之后,自动更新PC的值,即PC=PC+4=8+4=12=0xC
- 译指
- 指令周期Cycle3
- 执行(指令)
执行“A_BIT”,所对表达的含义.
- 译指
翻译"B_BIT"
- 取指
此步骤由于是和上面(1)中的执行同步做的,
-
而取指的那一时刻,PC为上一Cycle更新后的值,即PC=0x0c,
-
而取值后,cycle+4,所以是此时去取物理地址为0xc所对应的指令"C_BIT" PC=0xC+4=0xF;
-
- 执行(指令)
其实,分析到这里,大家就可以看出:
在Cycle3的时候,PC的值,刚好已经在Cycle1和Cycle2,分别加了4,所以Cycle3的时候,PC=PC+8,而同样道理,对于任何一条指令的,都是在Cycle3,指令的Execute执行阶段,如果用到PC的值,那么PC那一时刻,就是PC=PC+8。
所以,此处虽然是五级流水线,但是却不是PC=PC+16,而是PC=PC+8。
进一步地,我们发现,其实PC=PC+N的N,是和指令的执行阶段所处于流水线的深度有关,即此处指令的执行Execute阶段,是五级流水线中的第三个,而这个第三阶段的Execute和指令的第一个阶段的Fetch取指,相差阶段的值是 3 -1 =2,即两个CPU的Cycle(指令操作),而每个Cycle都会导致PC=+PC+4,所以,指令到了Execute阶段,才会发现,此时PC已经变成PC=PC+8了。
回过头来反观ARM7的三级流水线,也是同样的道理,指令的Execute执行阶段,是处于指令的第三个阶段,同理,在指令计算数据的时候,如果用到PC,就会发现此时PC=PC+8。
同理,假如ARM9的五级流水线,把指令的Execute执行阶段,设计在了第四个阶段,那么就是PC=PC+(第4阶段-1)*4个字节 = PC= PC+12了。从A指令的5级流水开始,执行取指操作"B_BIT"就会在A指令的第四阶段,那么就会有一个不同于三阶段的pc取值的延时操作。
如下:(横向轴)
取A 4 初始pc=0,pc=12/3=4_bit
译A 取B 8 A执行完成时,取指C,则 A,B,C.正是pc=pc+8
执A 译B 取C 12 pc空闲值为1
存A 执B 译C 取D 16
写A 存B 执C 译D
写B 存C 执D
写C 存D
写D
假设:(纵深加长,横向轴)
取A 4 4 从图可以看出pc空闲值=取指周期N*1,完全不符合计算机实时操作系统的要求
执A 取B 8 12 存A时,取指C,则ABC,正是三阶段pc=pc+12
存A 译B 取C 12 16 然而在四阶段的自身的pc来说还是,pc=pc+8(pc只有当取指时才会+4)
写A 执B ...
存B ...
写B ...
流水线优化级别为,译码阶段取指最高,避免资源浪费