原理

它通过使用硬件来支持指令级并行,从而能够处理某些在编译阶段无法知道的相关关系(如涉及内存引用时),并简化编译设计;能够允许一个流水线机器上编译的指令,在另一个流水线上也能有效运行

记分板的目的是,在没有资源冲突的前提下,使每条指令尽可能早的执行,以保持每一个时钟周期执行一条指令的速率。即,当某条指令将要执行的指令被暂停时,其他没有相关于任何正在执行或被暂停指令的指令,应该可以提到前面来发射并执行。

它的核心思路是:

(1)允许暂停指令之后的指令被执行,实现按序发射、乱序执行、乱序完成;

(2)对于乱序完成产生的WAR、WAW冒险,采用以下方法解决:对于WAR,要求排队等待操作以及他们操作数的拷贝,并只在读操作阶段才读取寄存器。对于WAW,则检测冒险,暂停并等待其它指令完成;

(3)把ID阶段分成Issue和Read Operands两段,这里将检测所有结构冒险,等待不存在数据冒险的情况,从而支持在保证按序发射的情况下乱序执行。

结构

图中给出了记分板的基本系统结构,记分板的功能是控制指令的执行,所有数据通过总线为这一组功能部件提供服务。不仅负责实现指令发射和执行的,也负责所有冲突的检测。

(1)每条指令都要从记分板部件通过,并在这里建立相应的数据相关结构,这一步代替了ID阶段的发射部分。

(2)由记分板部件决定何时可以读操作数、执行指令,如果判断还不能立即执行,则会监视硬件上的每一个变化并决定该指令何时才能执行。

(3)记分板还可以控制指令写入目标寄存器的操作。

这样,所有的冲突检测及解除工作都集中在记分板部件上。

记分板由三部分构成:

1)、指令状态。说明指令处于4个阶段中的哪个阶段(issue、read operands、execution、write back)。

2)、功能部件状态。指明功能部件的状态,每一个功能部件包括9个域。

Busy指明功能部件是否正被使用;Op指明功能部件正在进行的操作;

Fi指明目的寄存器;Fj、Fk指明源操作数所在的寄存器;

当源操作数不直接从寄存器取到,而要等待前面执行的指令的功能部件产生时,使用Qj、Qk分别指明Fj、Fk将由哪个功能部件产生;

Rj、Rk指明源操作数(即Fj、Fk)现在是否可用,若这两个域指示不可用,说明需要等待别的功能部件(即Qj、Qk)产生。

3)、寄存器结果状态。

指明哪个功能部件将写入该寄存器。如果没有指令将写入该寄存器,则该寄存器的状态为空白。

步骤

记分板用四个阶段代替ID、EX、WB三个阶段。4个阶段分别如下:

1)、issue阶段。该阶段完成指令译码,并检测结构冒险。

该阶段按程序的次序发射指令。当

需要发射的那条指令要用到的功能部件空闲(没有结构冒险),

而且待发射指令与已发射但尚未完成的指令之间没有输出相关——没有其他活动指令和该指令争用同一个目的寄存器时(没有WAW冒险),

记分板就直接把指令发射到功能部件并更新自己的内部数据结构。

否则(如果存在结构冒险或写写冒险)暂停发射任何后继指令,直至冒险解决。

(通过确保无其他活动的功能部件与其争用同一目标寄存器,可以杜绝WAW冒险。)

2)、读操作数(read operands)。等待更早发射但未完成的指令写回其结果,所以在该阶段可解决所有真数据相关。

记分板监视源操作数的可用情况,

如果没有更早发射的指令要写源操作数所在寄存器(没有RAW冒险),或者存放源操作数的寄存器此刻正在被某个活动的功能部件写入,那么源操作数是可用的。此时功能部件可以读取操作数。否则,暂停在该阶段直到满足条件。

通过这种方法,记分板解决了写读冒险,指令从而可以乱序的进入执行阶段。

3)、执行(Execution)。功能部件在得到操作数之后即开始执行,执行结束,结果产生后,通知记分板已经完成执行。

4)、写结果(write back)。当不存在WAR冒险时,功能部件写回结果到寄存器。

判断的方法是:如果在该执行完的指令之前的指令尚未读取其操作数(前面要读得还没读),且其中一个操作数使用的寄存器正好与等待写回结果的寄存器相同(先写得还没先),则判断为此时存在WAR。一旦WAR冒险被解决后,记分板就通知功能部件让其写回运算结果。

局限性

减少流水线暂停受到限制——指令中可并行的数量、记分板入口数量、功能部件的种类和数量、反相关和输出相关。

1)、没有前递硬件,只用寄存器传值;

2)、指令调度局限于基本块内,指令窗口小;而实际上程序中常常存在很多branch,使得基本块很小。

3)、功能部件少,容易引起结构冒险,特别是用得多的integer/load store部件;

——>存在结构冒险,就暂停发射指令,按序发射耽误了时间;

4)、由于寄存器不够多,存在WAR、WAW冒险。

——>需要等待,防止出现WAW冒险,直到WAR冒险解决