




摘" 要" 在計算機專業課程中,計算機體系結構課程是硬件類課程的重點和難點,為了學生更好地學習該課程,具有理論聯系實際和團隊協作能力,創新性地在課程中設置使用開源RISC-V指令集設計并實現無序流水線處理器的實驗。通過指令的無序調度算法,利用指令級并行性(ILP)、流水線設計、緩存、預取和虛擬內存實驗幫助學生掌握SystemVerilog語言,并且能夠使用RISC-V、GCC、自定義鏈接器編譯測試驗證程序和基準測試。教學結果證明,此創新實驗教學方法能夠使學生既掌握計算機體系結構課程中深奧的理論和枯燥的編寫、調試大型代碼庫的方法,又增強團隊協作能力和興趣,讓學生學以致用,為培養具有硬件設計能力的人才打下堅實基礎。
關鍵詞" 計算機體系結構;RISC-V;SystemVerilog語言;無序流水線;實驗
中圖分類號:G642.0" " 文獻標識碼:B
文章編號:1671-489X(2024)15-0-06
DOI:10.3969/j.issn.1671-489X.2024.15.122
0" 引言
全球對微處理器的需求屢創新高。同時,數據中心、移動和嵌入式設備對高性能的持續需求正在推動計算機向更加復雜的體系結構和新穎性設計發展。在過去的30年里,摩爾定律節奏正在放緩,最先進的CPU已經由大約100萬個晶體管組成的有序流水線核心(如Motorola 68040)發展到由數十億個晶體管組成的多核無序深度流水線處理器(如Apple A14),多級緩存、緩存一致性協議和同步多線程等技術性能得以提高,同時增加了設計和制作過程的復雜性。
然而,計算機體系結構高等教育并沒有跟上世界發展的步伐,即使是微小的嵌入式設備通常也包含流水線CPU[1]。現代計算機體系結構不僅是硬件設計行業的必要基礎,而且與學習構建高效可靠軟件領域高度相關。計算機專業課程不僅要教學生如何構建處理器,學習先進的設計方法,還要讓學生親身體驗無序流水線和多級緩存工作原理與過程。
為使學生深入理解現代處理器的功能,通過教學生設計實現處理器高級功能,包括緩存改進、超標量設計、高級分支預測器和多核/多線程設計等,培養學生硬件設計和團隊協作能力。提出現代計算機體系結構的一種新穎的教學方法,同時激勵學生進行現代計算機體系結構(GPU、FPGA、硬件/軟件協同設計等)的設計。通過學習現代計算機體系結構的背景知識,開展現代硬件的案例研究,以及安排的實驗項目,設計構建一個支持RISC-V[2]指令集子集的無序處理器,它基本涵蓋了從各種無序微架構到現在發展的有序流水線,包括多種利用無序執行的指令級并行性的方法,如圖1所示。
1" 相關工作
目前,有許多高等教育用途的RISC-V實現單周期流水線處理器,如Davis In-Order(DINO)CPU,它是基于Chisel的五級RISC-V流水線實現RV32I。DINO包括調試工具和功能測試,使學生理解底層架構,而不是僅僅作為輔助工具。類似的,WebRISC-V和BRISC-V平臺是基于網絡的RISC-V匯編模擬器,包括編譯和調試工具。這些教學工具有助于學生在導論課上學習,使教師能夠圍繞已知的微架構和系統設計布置作業。
筆者構建的課程項目與這些不同之處在于,教
學生如何設計無序CPU的核心(圖2)。學生以學習
過的前導課程為基礎,使用類似DINO的五級RISC-V
處理器開發一個更復雜的無序內核,這是現代高性能處理器的基礎。
2" 課程描述
該項目是計算機體系結構課程創新型實驗之一,學生需要掌握計算機組織(流水線、緩存和虛擬內存等)、軟件設計(簡單的數據結構和算法)和數字邏輯(邏輯門、組合和順序邏輯,最好有編寫Verilog或其他硬件設計語言如HDL的經驗)。最終目標是讓學生詳細了解單核CPU(包括核心流水線和緩存層次結構)是如何設計并與軟件交互的(圖3),演示設計和實現過程。
2.1" 實驗內容
實驗內容如表1所示。每個實驗要求在兩學時內完成,要求每個學生單獨完成,提交教師檢查。實驗中學生之間可以互相探討,找到最優方法,提高編碼效率。
2.2" 單項實驗
學生通過完成單項實驗復習基本的數字邏輯和計算機體系結構培養編寫組合和順序邏輯的技能,學會故障排除和修改代碼庫的方法。
2.2.1" 組合邏輯(優先級選擇器)
該實驗要求學生使用組合邏輯編寫優先級選擇器,并通過使用雙比特優先級選擇器構建更大的優先級選擇器進行分層模塊設計,向學生介紹常見的Verilog結構,如賦值語句和邏輯塊等。
2.2.2" 有限狀態機(整數平方根)
提供給學生一個四階段流水線設計的樣本乘法器,用來計算多個時鐘周期的部分乘積的和。要求學生重新配置乘數的流水線各個階段,綜合設計并提高基準性能,使學生知道如何設計使用編譯器,并在執行后進行合成模擬和基準測試,理解關鍵路徑和增加額外流水線階段之間的權衡關系。最終,學生設計出硬件模塊計算64位值的整數平方根(有效地在硬件中執行二進制搜索),為日后在Verilog中設計和實現有限狀態機積累
經驗。
2.2.3" 有序處理器
最后的單項實驗要求學生修復一個五級RV32IM
處理器中的流水線沖突。RV32IM是RISC-V的整數和
乘法擴展,支持位運算、條件和無條件分支、加載/
存儲、整數加法及乘法(無除法或浮點)。為學生提供標準五階段流水線的可整合的SystemVerilog實現方法,設計出通過內存接口和測試平臺集成所有流水線階段的頂層模塊。存儲器接口設計為一個連接到測試平臺函數的讀/寫總線(不使用組合
內存)。
這條流水線沒有對沖突進行控制。任意RV32IM程序(提供一個測試庫)可以通過在每個指令之間插入四個noop指令使之正確運行。設計期間教師指導學生解決三種沖突問題。
1)在解碼階段由寄存器讀數引起的數據沖突,學生必須實現檢測和轉發邏輯。
2)分支機構產生的控制沖突,學生要推測“沒有被執行”,以避免拖延進度。如果分支解析為“已取”,則在指令提交之前調整受影響的流水線階段。
3)由(模擬的)存儲總線引起的結構沖突。由于該總線一次只能接受一個請求,因此在流水線存儲階段和取指階段之間會產生爭用,必須將取指階段暫停一個周期。
鼓勵學生增加額外的邏輯,但要仔細思考后果。額外的寄存器意味著CPU可以使用更多的狀態,但也會在測試過程中發現更多的錯誤。
3" 處理器設計
處理器設計實驗在課程的最后八周進行,學生每五人一組,設計實現支持RV32IM的高性能無序處理器。通過每個測試用例的執行時間來衡量性能,即每個時鐘周期執行的平均指令(IPC)的函數。這個項目非常復雜,需要學生有非常扎實的理論知識和動手能力。
3.1" 設計原理
該實驗設計由兩個部分組成:基本特性和高級特性(表2)。這些特性由遵循英特爾P6或MIPS R10k風格微架構的無序流水線組成,包括指令和數據緩存、分支預測器和負載存儲單元等。圖2顯示了一個MIPS R10K風格的無序流水線示例,該流水線具有分派/分發邏輯和重排緩沖區(ROB)功能。
3.1.1" 啟動器代碼
學生可以自由重用有序處理器項目中的代碼,其中最重要的模塊是指令解碼器和算術邏輯單元,包括一個簡單的指令和數據緩存(32行,直接映射)。為了方便學生設計,提供一些參考實用模塊,如優先級選擇器,它可以在整個項目中任何需要仲裁的地方使用。有序處理器還充當一個真實的模擬器,在程序執行后形成內存映射,并把所有執行指令和寄存器記錄寫入日志。
3.1.2" 確保無序執行
要求學生使用單項項目中的部分積流水線乘法器來執行乘法指令,確保至少有一條指令需要多個周期,并且具有簡單的時鐘周期與延遲功能。在由一條乘法指令和一系列加法指令組成的重復循環運算中,即使是一個簡單的基準測試,也可以無序執行。學生決定如何將可用指令調度到流水線中的執行單元,可以有多種設計方法,如盡早調度高延遲指令、識別舊指令以避免空閑等。在實踐中,這些設計依賴優化的優先級選擇器,很難在單一的、短的時鐘周期內完成。因此,建議學生安排一個隨機指令執行,并在需要時優化問題邏輯。
3.2" 設計過程
在實驗正式開始之前,指導教師與每個小組討論實現具體高級功能的方案。表2顯示可以添加到設計中的功能列表。在實驗項目中,要求至少具有兩個簡單功能和一個高級功能以評價學生的設計
成果。
3.2.1" 編寫模塊
所有小組需要設計、調試完成一個正確的模塊。這期間,要鼓勵學生把該模塊作為一個整體進行編碼,使編碼風格和實踐具有一致性,并建議每個小組構建一個在整個設計期間都能使用的接口高級架構。第一個模塊作為不同單元之間的接口,通過引入小錯誤檢測模塊和測試平臺,并觀察測試平臺是否能夠捕捉到它們(例如,將“或”變為“與”,或者用減法代替加法等)。盡早發現和修改錯誤,使學生意識到單元測試的重要性。
在實驗中,講解如何編寫可參數化模塊,并要求第一個模塊是可參數化的,因為參數化更易于修改和優化設計分析。在編寫第一個模塊之前,教師解釋如何構建硬件的基本數據結構,如先進先出(FIFO)隊列、堆棧和位映像等。然后提供更多先進的設計方法。教師更多地作為顧問而不是講師,在設計選擇上給學生盡可能多的自由。
3.2.2" 流水線設計
設計第二個必要功能時,要求每組擁有一個功能性的無序流水線核心,能夠獲取和執行指令(但還沒有數據存儲操作)。學生在設計之前一周開始整合模塊,并完成與存儲無關的那些高級功能的設計。整合是一個困難而耗時的過程,不規范的編碼風格通常會導致模棱兩可的行為,甚至是錯誤。由于SystemVerilog模擬器能夠接受模棱兩可的代碼,使得這些錯誤在模擬后很難找到。為了解決這一問題,從學期開始就一絲不茍地教授規范的編碼風格。要求所有小組預留一周時間進行最后的存儲系統整合。
3.2.3" 調試和整合
學生進行單元測試時,要確保足夠大的測試覆蓋率,并組合單獨的模塊,只有當學生更早地進行更多的單元測試時,流水線整合才會更容易。學生可以訪問35個以上測試用例的測試集,并選擇用C或匯編語言編寫測試用例,也可以向測試集中加入新的測試用例。如果有了一個可以工作的流水線,就可以用相應的指令標記寄存器寫入歷史記錄,這是在不修改內存的情況下驗證正確性的唯一方法。此外,執行寄存器寫操作可以準確地識別執行錯誤的指令。此日志還用作已提交指令的列表,可以將其與有序內核生成的日志進行比較,以查看控制流指令(如分支和跳轉)是否選擇了正確的方向。在第二個實驗之后,當每個小組擁有一個可以修改內存的完整功能流水線時,檢查處理器所提供的有序處理器執行程序后產生的內存映射。
邏輯綜合是用HDL轉換為標準單元的網絡列表,這些單元可以是宏模塊(如加法器),也可以是簡單的邏輯門。這是硬件設計中的關鍵步驟,因為大多數設計是根據行為而不是硬件結構編寫的,但最終必須能夠被構建到實際的硬件中。學生常犯的錯誤是使用未初始化的值,這些值沒有被重置;或者沒有檢查有效性的值,導致錯誤值沿著流水線流動。在行為模擬中,這可能是隱藏的,因為通常傳遞的這些值不會影響其他邏輯。然而,在整合之后,標準單元寄存器生成的值為x,而不是0或1,這意味著不確定性。x可以向下傳播到其他邏輯產生不確定的值,極大地破壞處理器的運行狀態。
邏輯合成的另一個指標是性能。每個小組通過測試程序的總運行時間進行基準測試,這是執行的循環數和時鐘周期的乘積。綜合實驗包括設計靜態計時,并報告關鍵路徑、區域和其他潛在問題,如循環邏輯。為了減少關鍵路徑的延遲,可以在邏輯鏈中添加更多的流水線,減少數據結構的規模,有時甚至完全舍棄某些功能。如何掌握每條指令周期(CPI)與時鐘速度之間的重要權衡,這是每個邏輯設計都要面臨的問題。
3.3" 學生報告和項目評分
提交項目后,學生要寫一份最終報告,詳細介紹他們的設計過程和功能。筆者對高級功能的性能評估特別感興趣,作為教師,每個學期都能發現一到兩個新穎的設計。在某些情況下,要求學生演示一個高級功能,以證明它可以正常工作,并且要求每個小組把他們的設計向全班學生作10分鐘的宣講,再次展示高級功能或獨特之處。
使用自動評分工具運行所有的基準測試程序,并通過最終的內存狀態檢查正確性。自動評分器還為每個項目提取循環計數和時鐘周期,并根據每個組的相對性能計算一個標準化的綜合分數。最困難的過程是整合每個小組的項目,以確保它在整合后能正常工作。通過手工檢查代碼檢查是否作弊,作弊行為罕有發生。
4" 特性設計
學生設計的高級功能是實驗的重要組成部分,學生可以使用不同的技術提高性能。每個團隊都要演示所實現的高級特性效果,并展示對測試程序性能的影響,或者解釋性能受到影響的原因。
4.1" 獨特的特性
4.1.1" 高級分支預測器
學生至少要提供一個分支目標緩沖區和簡單的(如雙峰)分支預測器。在本學期中,學生要實現一個全局的Gshare、TAGE或其他高級分支預測器。因為任何分支預測器最終都是推測性結構,所以證明高級分支預測器算法的正確性是比確保執行正確性更困難的驗證問題。此外,高級的分支預測器設計(如TAGE)是不能改進標準測試程序性能的,因為沒有任何程序能夠提供足夠多指令來預熱預測器,因此要求學生提供(如果可能的話)一個示例程序,證明該程序(即使是人工設計的)使用分支預測器比使用普通的分支預測器執行效率更高。
4.1.2" 超標量(2級)
大多數學生通過增加流水線階段來支持多條指令實現超標量設計。要求學生設計支持2級超標量流水線,它可以在每個時鐘周期內從主存加載或存儲單個64位的塊數據,使性能顯著提升,而3級或更高的超標量對性能的提升逐級遞減(也與緩存容量有關)。最好在初始設計時將每個模塊設計為超標量,因為在項目后期將模塊重寫為超標量十分困難。一般來說,學生會在許多測試程序上看到由于超標量的設計使得性能有顯著的提高,這也促使學生想方設法設計更多的高級功能。
4.1.3" 改善緩存和加載/存儲隊列
為學生提供簡單的32行直接映射數據和指令緩存,對它可以設計多項改進措施,而且在概念上比較簡單,這些優化改進使數據緩存成為其設計中最復雜的模塊。通過回寫技術可以減少內存總線上的通信量,提升系統性能。緩存組相聯的設計能夠減少相互沖突,其中實現2路或4路緩存比較簡單,但全關聯的緩存設計具有很大的難度。
4.1.4" 提前預測分支
推測分支必須在重排緩沖區(ROB)指令交回之前確定。可以更早地預測一個分支,并部分清除ROB以糾正新的分支目標。由于每個周期都需要一個算法檢查多條指令,并跟蹤已預測的指令,因此,要求在一個時鐘周期內完成是非常困難的,這正是要進行性能改進之處。
4.1.5" 預取
預取是學生實現的最常見的特性之一,概念上非常簡單,即從內存取指時,獲取比當前指令更多的指令。使用32位ISA和64位存儲器,好處是在每個塊中可以多存儲一些指令。使用能夠獲取下一個或兩個數據塊的簡單多步預取器可以很好地改進性能,而能夠正常工作并調試更復雜的預取器的設計是更難的,所以要求學生每組設計不超過32行的緩存,這樣對于設計更方便,但也使得不清除有效指令的預取受到一定的限制。
4.1.6" 異常處理
雖然還不支持異步異常(中斷),但允許學生實現由系統調用或模擬某些指令(如divide)觸發的異常。為了實現這一點,學生的設計必須支持系統調用,如MCALL和MRET,并將控制狀態寄存器(CSRs)集成到內核中。為了正確而且有序,學生必須確保系統調用是流水線中唯一的指令,且ROB必須為空,在系統調用退出之前不能發送其他指令。為學生提供一個軟件異常處理程序以及模擬除和求余指令的技術。
4.1.7" 多線程(SMT)
SMT的主要挑戰是在核心流水線和緩存層次結構中實現加載鏈接和條件存儲指令。這要求學生掌握互斥對象和共享內存的概念,這些知識已經從其他課程或經驗中學習過,所以如果擁有LL/SC操作碼的硬件支持,他們就可以設計出使用兩個線程實現的自加計數器。由于該特性具有一定的復雜性,通常會安排一個演示會議,在這個會議上,團隊將展示他們已經正確實現了該特性。教師通常會獎勵那些成功實施這一措施的學生團隊10%的成績
加分。
4.1.8" 多核心
鼓勵設計實現多核心的團隊快速設計一個簡單的內核,這樣他們就有幾周的時間研究緩存一致性。為了獲得該特性的滿分,團隊必須演示兩個具有MSI協議和交叉存取線程的核心通信。對于要實現此功能的小組,在幾周前舉辦一到兩場講座教授MSI/MESI協議,并要求團隊演示他們的設計。
4.2" 學生的設計
學生更喜歡用最少的工作量獲得最多性能收益的高級功能。幾乎所有組(每學期除了一兩個組外)實現了超標量和一些緩存改進。雖然偶爾有雄心勃勃的團隊會做一些獨特的設計,但通常情況下,使用R10K微架構的團隊還是遠多于使用P6的團隊。許多小組構建了更高級的分支預測器(即比簡單的雙峰預測器更復雜),而實現提前分支預測的小組通常喜歡使用更簡單的預測器。多核、多線程和異常處理仍然是小眾的選擇,因為每一個都比常見的特性更難實現,并且需要相對較高的成本費用。
5" 調查與統計
在項目結束后對學生進行調查,獲得學生對項目難度水平、編譯器在測試用例中的作用、如何提高技能、對計算機體系結構的理解和看法,如表3所示。結果顯示,學生認為該項目提高了他們的SystemVerilog技能和對計算機體系結構概念的理解,認為流水線整合階段比模塊設計階段更困難,可能由于在這些階段暴露的錯誤較多;只有大約一半的人使用編譯器,并且那些使用的人發現編寫他們的測試用例進行調試很有用。
6" 結束語
本文描述了高等教育中計算機體系結構課程的
創新型實驗內容和設計的過程,學生通過學習指令
的無序調度算法、指令級并行性(ILP)、流水線設
計、緩存、預取和虛擬內存實驗熟練掌握System-Verilog語言,使用RISC-V、GCC、自定義鏈接器編
譯測試驗證程序和基準測試。結果證明,這種創新教學方法可以讓學生既掌握計算機體系結構課程中深奧的理論和編寫、調試大型代碼庫的方法,又增強團隊協作能力,使硬件類課程知識學以致用,為培養具有硬件設計能力的人才打下堅實基礎。
7" 參考文獻
[1] 陳田,丁賢慶,路強,等.案例教學法在計算機系統結構課程中的應用[J].計算機教育,2018(9):85-88.
[2] 王旭,李麗斯,趙爍,等.基于RISC-V指令集的超標量處理器設計[J].中國集成電路,2020,29(9):35-41.
[3] 闕慶河.一種低開銷高性能的RISC-V處理器設計[J].單片機與嵌入式系統應用,2021,21(1):14-18.
[4] 張曉磊,白俊峰,王德弘,等.基于雨課堂的桿塔結構設計課程混合式教學模式實踐[J].中國教育技術裝備,2023(10):46-49.
[5] 張晨曦,王志英,沈立,等.計算機系統結構教程[M].北京:清華大學出版社,2021:64-86.
[6] 李昭,劉有耀,焦繼業,等.超標量處理器亂序提交機制的研究與設計[J].計算機工程,2021,47(4):180-186.
*項目來源:黑龍江省教育科學“十四五”規劃2023年度重點課題(GJB1423136);佳木斯大學教育教學改革研究項目(2022
JY2-47);佳木斯大學教育教學改革研究項目(2022JY3-60)。
作者簡介:常亮,博士研究生,講師;郭宇飛,通信作者,博士研究生,講師;閆文剛,講師。