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或者long4. inst0是long或者fence且id級沒有發生stall |
ctrl_id_pipedown_2_inst | 4. inst0/1都是normal或者short 且inst2是long或者fence5. inst0/1都是short,inst2是short/long/fence |
ctrl_id_pipedown_3_inst | 1. inst 0,1,2 兩個short一個normal2. inst 0,1,2 一個short兩個normal且inst3 fence或long3. 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
本文章僅供學習交流使用,如引用請標註出處。