IssueQueue
- 版本:V2R2
- 状态:OK
- 日期:2025/01/20
- commit:xxx
设计规格
- 支持 4 类不同的发射队列模块以适配标量整型,向量浮点,标量访存和向量访存
- 支持两个入队口两个出对口
- 支持推测唤醒信号产生
- 支持推测唤醒信号寄存器复制
- 支持指令写回冲突提前判定
- 支持就绪指令中选择最老指令发射
功能
发射队列模块作为处理器乱序调度的起点,连接前一级 Dispatch 流水级和后一级 DataPath 流水级。在超标量乱序处理器中,为了实现指令的正确乱序执行,需要正确处理器指令间的依赖关系,描述指令是否能够正确执行的关键就是每条指令源操作数的就绪情况,当源操作数依赖的前面的指令执行完成后,该源操作数才进入就绪状态。IQ 接收从 Dispatch 阶段分派而来的至多两条指令,指令的源操作数可能还未就绪,指令会暂存在IQ内部,IQ 实时监听唤醒信号,唤醒信号会将其对应的源操作数由未就绪置为就绪。每个周期,IQ 内部会选出最多两条操作数都就绪的指令,并遵循最老最优先策略,发往后续的 DataPath 流水级。发射队列通过上述方法,保证了指令乱序执行时,所有指令间依赖关系均能得到保证,并尽可能提升乱序调度的性能。
指令入队
4 类不同的发射队列的指令入队逻辑基本一致,仅因部分信号的不同而有些许差异。发射队列内部实例化了 Entries 模块负责指令的存储,一般情况下,发射队列支持两个入队口,即每周期至多从前一流水级接收 2 条有效指令,故与之对应的,Entries 模块同样支持两个入队口。 指令入队过程,即通过 IQ 的输入端进入,选出关键信号,送至 Entries 的输入端,这个过程中,诸如 robIdx,fuType 等指令自带信号不做额外处理直接接入;而 srcState 等指示指令状态的信号,会在进入 Entries 之前通过部分组合逻辑进行初始化赋值。各信号详细信息参见 Entries 接口文档。 本发射队列支持指令入队的同时进行唤醒,基于时序考虑,唤醒逻辑并未直接在指令进入 Entries 之前实现,而是采用将输入唤醒信号送入 Entries 后,同步打拍后再唤醒的方法。
指令年龄关系维护
为了实现指令发射选择的最老最优先策略,在发射队列内,需要每个周期对存在 Entries 内的指令进行指令年龄的记录和处理。发射队列内部实例化了若干个 AgeDetector 模块进行这部分功能的实现。对应 3 类不同的 Entry,发射队列需要实例化至多 3 个 AgeDetector。每个年龄矩阵可同时接收多个出队端口的年龄查询,并返回查询中最老的一项。AgeDetector 每周期接收 Entries 反馈的 3 类 entry 的入队状态,负责维护全部指令的年龄关系,直观来说,当一条指令入队时,它的年龄必然是全部指令中最年轻的;发射队列通过 Entries --> AgeDetector 的信号传递实现指令年龄关系的维护,并在指令发射选择阶段通过读取 AgeDetector 完成最老最优先策略的运用。
指令发射选择
发射队列将 Entry 分为至多 3 类,并支持了指令在 Entry 之间存储位置的转移,3 类 Entry 之间有着严格的年龄关系,所以指令发射选择,也分别针对 3 类 Entry 进行并行选择,最后再进行 3 选 1 选择最老的指令发射。基于时序考虑,为了满足发射队列两出队端口的需求,设计优先满足第一个出队端口的需要,功能实现为:依据 EnqEntry/SimpleEntry/ComplexEntry 三类 Entry 对应的三个 Detector,分别选出三条最老能发射指令,而后依据三类 Entry 间严格的年龄关系,按照 Complex > Simple > Enq 的优先级顺序最终选出一条,送往第一个出队端口;对于第二个出队端口,取决于出口 fu 的配置:如果两个出口的 fu 不同,那么他们可出队的指令不会重叠,第二个口也按第一口的方法选出一条最老指令;如果两个出口的 fu 相同,就可能重叠,因此屏蔽掉第一个口的选择结果后,“随机”选一条有效指令。目前的 IQ 配置中,两个口的 fu 都是不同的(或者就只有一个出口),因此不存在“随机”选的情况,就不再赘述“随机”的具体流程。
推测唤醒信号产生
发射队列负责管理指令,不仅包括对指令何时发射的管理,还包括告知其他指令何时发射的管理,后者即是通过推测唤醒实现的。在一般情况下,如果一条指令的源操作数依赖于前一条指令的写回值,那么只有前一条指令写回时,当前指令的源操作数才能被置为就绪状态。为了提升指令乱序执行的性能,实际上如果前一条指令是固定执行延时的指令,那么当它从发射队列发射出去时,就能够确定其何时写回,相应的便可以在某个时刻由发射队列发出推测唤醒信号,只要保证被推测唤醒的指令,取得源操作数的时刻不早于前一条指令得到结果的时刻,便可通过 forward、bypass 等方式加速指令的乱序执行。在发射队列中,对于非访存 IQ 负责产生推测唤醒信号的模块就是 WakeupQueue,指令被选择发射的同拍,也会进入 WakeupQueue 中,根据其执行延迟,进入不同的移位 pipeline,0 lat 则一拍后产生推测唤醒;2 lat则三拍之后,以此类推。通过这种方式,可以实现推测唤醒信号的产生。对于访存 IQ,其唤醒信号使用访存 IQ 独有的 loadWakeUp 接口从访存单元传入,将其打一拍后,当做 IQ 自己的唤醒信号,再走和前面 WakeupQueue 相同的接口广播给其他 IQ。
写回冲突的提前判断
写回冲突分为两个部分。 第一部分,是 IQ 出口自身的写回冲突。发射队列每个出队端口对应一个 EXU,每个 EXU 里可能有一组 Fu,这一组 Fu 的执行延迟不尽相同,而每个 EXU 只有一个写回端口(指写回 rob 的写回端口,与寄存器堆的写口不同,一或多个 EXU 写回口共用一个寄存器堆写口)。比如 Alu 与 Mul 的 Fu 组合,会产生 0 lat 和 2 lat 的写回冲突问题,如果一条 0 lat 指令在 2 lat 指令发出两拍后发射,就会同时执行完成,产生 Fu 写回冲突。为了避免这类情况的发生,发射队列内部实例化了 fuBusyTable 模块进行 Fu 冲突的判断。fuBusyTable 以出队端口为基本单位,记录各自的出队端口每周期出队的指令及各自的反馈信号,以此修改记录值,后续指令的选择发射也需要参考此模块的记录值情况,以此避免 Fu 写回冲突。 第二部分,是寄存器堆的写回冲突。由于寄存器堆的写口有限,多个 EXU 的写回端口可能共用一个寄存器堆的写口,因此发射队列之间可能发生写口共用,此时同样可能产生写口冲突的问题。类似地,发射队列中实例化了 intWbBusyTable 和 vfWbBusyTable,每当指令发射时,便产生相应的写逻辑,送至外部的 WbFuBusyTable 模块中将写口相同的取或处理,得到最终的 WbFuBusyTable;指令发射选择时,则根据写口从外部读取 WbFuBusyTable 送入 IQ 内部作为选择参考。
整体框图
接口时序

二级模块 WakeupQueue
控制各个 IQ 发出推测唤醒信号的关键模块,作为推测唤醒的唤醒源且非访存的 IQ 的各出队端口各自对应一个,模块内部由若干条流水线构成,流水线的条数和出队端口对应的 Fu Latency 直接相关,出队端口对应的 Fu 有几种 Lat,就有几条相应的流水线。
整体框图
接口时序

二级模块 AgeDetector
此模块为年龄矩阵模块,维护发射队列中各个 Entry 内指令的新旧顺序,发射队列的 Entry 至多三类,对每类 Entry,它们的 AgeDetector 模块都是独立的。 此模块使用矩阵寄存器标识 Entry 间的年龄关系,矩阵的行列均和 Entry 的个数一致,下面以 6 项的 SimpleEntry 为例:
整体框图