1、 IDU简介
IDU是玄铁C910中负责指令译码、寄存器重命名、派遣和发射逻辑的单元,主要划分为四级流水级,分别为ID、IR、IS、RF,玄铁C910中流水线分为控制通路和数据通路。本文将从流水级从前到后的顺序,介绍玄铁C910译码单元逻辑设计,以及在玄铁C910基础上进行扩展四发射所涉及逻辑。
2、 指令译码(id)
(1)指令类型
玄铁C910中支持的指令集分为RV基础指令集(IMAFDC)以及玄铁扩展指令集。根据指令类型,玄铁C910的译码单元将指令分为4种,分别为normal、split_short、split_long、fence。在译码单元中,标准的RISC-V指令会被分解成微操作(uop)。
类型 | Uop数量 |
Normal | 1 |
Split_short | 2 |
Split_long | 1~5 |
fence | 特殊指令 |
其中,Split_long和fence类型指令由于其特殊性,只作为inst0译码,当周期只能译码一条指令。在玄铁C910中,split_long类型的指令只有原子指令一种,其译码由状态机控制,如果分解出了5条微操作,那么在当周期无法全部pipe到下一级,会寄存一拍。
译码单元对应的分为normal、split_short、split_long、fence四种,玄铁C910采用并行的数据通路的设计,以面积换取时序,共有三组译码单元,第一组可译码split_long和fence类型的指令,其他两组为normal和short。
(2)指令回填
在玄铁C910中,ID级负责将IB级pipe的指令进行译码,其遵循一次回填三条的原则。如IB级pipe了三条指令,而ID级只能译码两条,那么下周期IB级不再向ID级发送指令,ID级将剩余的指令进行移位处理,下一周期只译码剩余的指令。
指令回填的逻辑由ctrl_id_pipedown_x_inst信号控制,主要的回填逻辑如下表
ctrl_id_pipedown_1_inst | 1. inst0是normal或short,inst1是fence或者long2. inst0是long或者fence且id级没有发生stall |
ctrl_id_pipedown_2_inst | inst0/1都是normal或者short 且1. inst0和inst1都是short,inst2是normal2. inst0,1,2都是short类型3. inst2是long或者fence类型 |
ctrl_id_pipedown_3_inst | Inst0,1,2中不能有fence或者long类型指令且inst 0,1,2不能有两条及以上的short类型 |
(3)微操作数量判定
译码级译码出的微操作数量最大为4条,因此译码级pipedown的微操作取决于id级的指令类型。在玄铁C910中,pipedown的uop的vld为
ctrl_id_pipedown_instx_vld
其主要判断逻辑为if-else逻辑,对于每条微操作的vld,从inst0指令类型判断到inst2指令类型。
对于uop0:
Uop0只需考虑inst0指令类型,因为是并行的译码通路,vld信号经过一个选择器
对应关系为
其中long_ vld[x] long类型的指令译码出的第几条微操作是否有效。
fence_ctrl_instx_vld:取决于fence状态机,在此简单介绍:
fence指令需要等待之前所有的指令都退休了,才能进行后续的指令译码。
fence_ctrl_inst0_vld表示,fence状态机到了issue状态,表示后续指令可以继续译码和pipe了。
fence_ctrl_inst1_vld 和fence_ctrl_inst2_vld为高时,fence 指令类型为FENCE.I指令以及玄铁扩展的虚拟内存广播指令以及状态机为issue状态。
ctrl_id_pipedown_x_inst信号在判定中作用很大,在考虑这个信号的基础上判断是否有效
Uop1需要考虑inst0和inst1
Uop2考虑inst0,1,2
(4)stall逻辑
Stall逻辑主要包括
1、 ir stall:ir级发生stall会同时stall ID级
2、 split_long stall:在开源版本中只有一种,原子指令译码出5条微操作时会产生此种stall。
3、 id bypass stall:发生了ir stall 或者当周期不能pipe3条指令时发生此stall。
Fence、long以及ir stall 三种会产生ID级pipedown stall。
(5)四发射修改
对四发射主要逻辑修改与上述所列类似,主要包括指令回填以及指令pipe
1、指令回填主要逻辑表格如下:
ctrl_id_pipedown_1_inst | 3. inst0是normal或short,inst1是fence或者long 4. inst0是long或者fence且id级没有发生stall |
ctrl_id_pipedown_2_inst | 4. inst0/1都是normal或者short 且inst2是long或者fence 5. inst0/1都是short,inst2是short/long/fence |
ctrl_id_pipedown_3_inst | 1. inst 0,1,2 两个short一个normal 2. inst 0,1,2 一个short两个normal且inst3 fence或long 3. inst 0,1,2 三个normal且inst3是fence或者long |
ctrl_id_pipedown_4_inst | 1. inst0,1,2,3中最多有一个short,其他都是normal且不能有fence也不能有long |
2、微操作pipe主要逻辑如下:
3、 指令重命名和预派遣(IR)
(1) 指令队列
在IS级派遣指令前,需要根据指令信息决定要派遣到的队列,在指令译码后,根据指令类型将指令分别送往7条队列,每个队列有两个写入端口分别为c0和c1,c0从队列左侧写入,c1从队列右侧写入。对于可以派遣到两条队列的指令,如某些AIQ0和AIQ1都能派遣的指令,优先级为A0c0>A1c0>A0c1>A1c1。
指令队列 | 表项数 | 指令发射的执行级 |
AIQ0 | 8 | ALU、DIV、SPECIAL |
AIQ1 | 8 | ALU和MUL |
BIQ | 12 | BIU |
LSIQ | 12 | LSU |
SDIQ | 12 | LSU |
VIQ0 | 8 | FALU、FMUL和FDIV |
VIQ1 | 8 | FALU和FMUL指令 |
(2) Stall和反馈机制
由于每个队列只有两个写入端口和一个写出端口,因此当同周期出现三条及以上某队列类型的指令时,当周期无法将全部的指令写入到指令队列中,如果直接stall流水线会造成性能损失。因此玄铁C910中加入了反馈机制,在ir和is两级流水之间增加反馈判断逻辑。
1、 typestall处理
stall分为 ir_stage_stall 和type_stall
其中type_stall可以通过反馈机制优化
当ir和is 的指令数量<4条时,可以反馈来避免stall
反馈信号主要是
ctrl_xx_is_inst0_sel[0] 表示is级pipe了2条(说明is级有3条同类型指令)
ctrl_xx_is_inst0_sel[1] 表示is 级不是pipe了两条
当is级pipe了两条时,以下两种情况会发生stall
如果is inst3 vld(说明is级pipe了两条,剩了2条 (inst2 inst3)指令)且 ir级inst2 vld(说明ir有3条及以上(0,1,2)的指令),此时超过了最大微操作数量4条,因此需要stall流水线。
如果is inst3 不vld(说明is级剩(inst2 )的指令)且 ir级inst3 vld(说明ir有4条及 (0,1,2,3)指令,超过最大微操作数量4,因此stall流水线。
ctrl_xx_is_inst_sel[0] | Is pipe两条 且is inst3 vld (说明剩了2,3两条uop) |
ctrl_xx_is_inst_sel[1] | Is pipe两条 且!is inst3 vld(说明剩了2一条uop) |
ctrl_xx_is_inst_sel[2] | 没有发生typestall的情况 |
(3) 动态平衡
对于AIQ0和AIQ1 以及VIQ0和VIQ1,因为存在aqi01和viq01类型的指令,而写入优先级总是A0>A1,因此aiq0和viq0中的指令数量会变多,增加stall的风险,因此玄铁c910中加入了动态平衡机制来解决这个问题
动态平衡机制通过对队列表项进行计数来实现。可以通过cp0配置信号来开启和关闭。
有两种情况会使能
1、 AIQ0(VIQ0)中表项数量为8且AIQ1(VIQ1)中表项数为0
2、 AIQ0(VIQ0)中表项数量和AIQ1(VIQ1)表项数量相差 2~7个之间。
这两种情况下会把AIQ01(VIQ01)变成AIQ1(VIQ1)类型的指令,然后再进行预派遣。
(4) 指令派遣
指令派遣逻辑主要分为两部分,队列端口的enable信号和队列端口要写入哪条指令的sel信号。其中AIQ和VIQ两条队列是特殊的,因为存在AIQ01和VIQ01类型的指令,因此在逻辑判断上要更复杂。
1、AIQ/VIQ队列端口的使能逻辑
a0c0 | 4条uop中有一条及以上的aiq0或者aiq01类型指令 |
a1c0 | 1、1条及以上的aiq1类型指令2、1条及以上的aiq0类型指令且一条及以上的aiq01类型指令3、2条及以上的aiq01类型指令 |
a0c1 | 1、2条及以上的aiq0类型指令2、1条及以上的aiq0,1条及以上的aiq1,1条及以上aiq013、三条及以上的aiq01类型 |
a1c1 | 1、2条及以上的aiq1类型指令2、2条及以上的aiq0,且1条及以上的aiq1且1条及以上aiq013、2条及以上的aiq01且3.1、2条及以上aiq03.2、1条及以上的aiq0,一条及以上aiq14、3条及以上aiq01且1条aiq0或者1条aiq15、4条aiq01类型指令 |
2、 AIQ/VIQ指令队列的派遣逻辑
Sel逻辑用于数据通路选择对应的指令
3、 其他队列端口的使能逻辑,以BIQ为例
按照inst0 – inst3的优先级分配端口即可。
(5) 指令折叠
指令折叠是玄铁C910中用来节约ROB表项的优化。AIQ0、AIQ1、AIQ01和VIQ0、VIQ1、VIQ01类型的指令可以进行fold,是否可以进行fold需要进行判定
assign ctrl_ir_pre_dis_inst0_fold = ctrl_ir_pre_dis_inst0_vld
&& ctrl_ir_inst0_fold
&& !ctrl_ir_inst0_split
&& !ctrl_ir_inst0_intmask
&& !rtu_idu_srt_en
&& !cp0_idu_rob_fold_disable;
Fold具有下面几种组合
ctrl_ir_pre_dis_inst01_fold
ctrl_ir_pre_dis_inst12_fold
ctrl_ir_pre_dis_inst23_fold
ctrl_ir_pre_dis_inst012_fold
ctrl_ir_pre_dis_inst123_fold
fold折叠必须要有连续2条以上可以fold的指令。
(6) ROB端口
在IR流水级中,会向ROB的表项中写入指令的相关信息,完成寄存器重命名过程。
在发生了指令折叠时,写入的是折叠的第一条指令的信息,同时记录折叠的指令数量。
所以虽然写入的都是折叠的第一条指令的信息,但是需要记录折叠情况,所有需要sel。
所以sel对应的数字其实没有特定意义,只是表示不同的情况,用于数据通路选择。
1、ROB 端口enable判断
2、ROB sel逻辑
3、 ROB IID逻辑
IID是表示指令先后顺序的标志位,也是ROB64个表项的索引。经过折叠的指令具有相同的iid。
4、 指令队列
1、 队列维护
队列的维护主要分为写入和弹出。写入在IS级写入,根据指令的类型送入不同的指令队列,写入端口为两个,pop端口为一个。队列会有表项数的计数,同时将信号传递个IR级进行DLB的控制。Create0的创建优先级为entry0-entry7,create1的创建优先级为entry7-entry1。
表项中主要维护以下内容:
① 年龄向量(agevec)
年龄向量是表示队列中表项的先后顺序的信号。队列的发射是顺序的,遵循先入先出原则,队列pop的指令是队列中最老的指令。
Create0和create1的年龄向量判断略有不同,因为在同一个周期中,create·0的指令一定比create1的指令要老。
2、 队列bypass
队列中表项的src0,src1,src2
都可以bypass
本文章仅供学习交流使用,如引用请标注出处。