ARM流水線解析
原文章地址:http://blog.chinaunix.net/uid-25070882-id-3069318.html
流水線技術通過多個功能部件並行工作來縮短程式執行時間,提高處理器核的效率和吞吐率,從而成為微處理器設計中最為重要的技術之一。ARM7處理器核使用了典型三級流水線的馮·諾伊曼結構,ARM9系列則採用了基於五級流水線的哈佛結構。通過增加流水線級數簡化了流水線各級的邏輯,進一步提高了處理器的效能。 ARM7的三級流水線在執行單元完成了大量的工作,包括與運算元相關的暫存器和儲存器讀寫操作、ALU操作以及相關器件之間的資料傳輸。執行單元的工作往往佔用多個時鐘週期,從而成為系統性能的瓶頸。
1 ARM7/ARM9流水線技術1.1 ARM7流水線技術 ARM7系列處理器中每條指令分取指、譯碼、執行三個階段,分別在不同的功能部件上依次獨立完成。取指部件完成從儲存器裝載一條指令,通過譯碼部件產生下一週期資料路徑需要的控制訊號,完成暫存器的解碼,再送到執行單元完成暫存器的讀取、
流水線中阻斷現象也十分普遍,下面就各種阻斷情況下的流水線效能進行詳細分析。
2.1 帶有儲存器訪問指令的流水線
對儲存器的訪問指令LDR就是非單週期指令,如圖2所示。這類指令在執行階段,首先要進行儲存器的地址計算,佔用控制訊號線,而譯碼的過程同樣需要佔用控制訊號線,所以下一條指令(第一個SUB)的譯碼被阻斷,並且由於LDR訪問儲存器和回寫暫存器的過程中
需要繼續佔用執行單元,所以下一條(第一個 SUB)的執行也被阻斷。由於採用馮·諾伊曼體系結構,不能夠同時訪問資料儲存器和指令儲存器,當LDR處於訪存週期的過程中時,MOV指令的取指被阻斷。因此處理器用8個時鐘週期執行了6條指令,指令平均週期數(CPI)=1.3個時鐘週期。
2.2 帶有分支指令的流水線當指令序列中含有具有分支功能的指令(如BL等)時,流水線也會被阻斷,如圖3所示。分支指令在執行時,其後第1條指令被譯碼,其後第2條指令進行取指,但是這兩步操作的指令並不被執行。因為分支指令執行完畢後,程式應該轉到跳轉的目標地址處執行,因此在流水線上需要丟棄這兩條指令,同時程式計數器就會轉移到新的位置接著進行取指、譯碼和執行。此外還有一些特殊的轉移指令需要在跳轉完成的同時進行寫連結暫存器、程式計數暫存器,如BL執行過程中包括兩個附加操作——寫連結暫存器和調整程式指標。這兩個操作仍然佔用執行單元,這時處於譯碼和取指的流水線被阻斷了。
2.3 中斷流水線處理器中斷的發生具有不確定性,與當前所執行的指令沒有任何關係。在中斷髮生時,處理器總是會執行完當前正被執行的指令,然後去響應中斷。如圖4所示,在 Ox90000處的指令ADD執行期間IRQ中斷髮生,這時要等待ADD指令執行完畢,IRQ才獲得執行單元,處理器開始處理IRQ中斷,儲存程式返回地址並調整程式指標指向Oxl8記憶體單元。在Oxl8處有IRO中斷向量(也就是跳向IRQ中斷服務的指令),接下來執行跳轉指令轉向中斷服務程式,流水線又被阻斷,執行0x18處指令的過程同帶有分支指令的流水線。
3 五級流水線技術五級流水線技術在多種RISC處理器中被廣泛使用,被認為是經典的處理器設計方式。五級流水線中的儲存器訪問部件(訪存)和暫存器回寫部件,解決了三級流水線中儲存器訪問指令在指令執行階段的延遲問題。圖5為五級流水線的執行情況(五級流水線也存在阻斷)。
3.1 五級流水線互鎖分析 五級流水線只存在一種互鎖,即暫存器衝突。讀暫存器是在譯碼階段,寫暫存器是在回寫階段。如果當前指令(A)的目的運算元暫存器和下一條指令(B)的源運算元暫存器一致,B指令就需要等A回寫之後才能譯碼。這就是五級流水線中的暫存器衝突。如圖6所示,LDR指令寫R9是在回寫階段,而MOV中需要用到的 R9正是LDR在回寫階段將會重新寫入的暫存器值,MOV譯碼需要等待,直到LDR指令的暫存器回寫操作完成。(注:現在處理器設計中,可以通過暫存器旁路技術對流水線進行優化,解決流水線的暫存器衝突問題。)
雖然流水線互鎖會增加程式碼執行時間,但是為初期的設計者提供了巨大的方便,可以不必考慮使用的暫存器會不會造成衝突;而且編譯器以及彙編程式設計師可以通過重新設計程式碼的順序或者其他方法來減少互鎖的數量。另外分支指令和中斷的發生仍然會阻斷五級流水線。3.2 五級流水線優化採用重新設計程式碼順序在很多情況下可以很好地減少流水線的阻塞,使流水線的執行流暢。下面詳細分析程式碼優化對流水線的優化和效率的提高。 要實現把記憶體地址0x1000和Ox2000處的資料分別拷貝到0x8000和0x9000處。 Oxl000處的內容:1,2,3,4,5,6,7,8,9,10 Ox2000處的內容:H,e,l,l,o,W,o,r,l,d 實現第一個拷貝過程的程式程式碼及指令的執行時空圖如圖7所示。
全部拷貝過程由兩個結構相同的迴圈各自獨立完成,分別實現兩塊資料的拷貝,並且兩個拷貝過程極為類似,分析其中一個即可。 T1~T3是3個單獨的時鐘週期;T4~T11是一個迴圈,在時空圖中描述了第一次迴圈的執行情況。在T12的時候寫LR的同時,開始對迴圈的第一條語句進行取指,所以總的流水線週期數為3+10×10+2×9=121。整個拷貝過程需要121×2+2=244個時鐘週期完成。 考慮到通過減少流水線的衝突可以提高流水線的執行效率,而流水線的衝突主要來自暫存器衝突和分支指令,因此對程式碼作如下兩方面調整: ①將兩個迴圈合併成一個迴圈能夠充分減少迴圈跳轉的次數,減少跳轉帶來的流水線停滯; ②調整程式碼的順序,將帶有與臨近指令不相關的暫存器插到帶有相關暫存器的指令之間,能夠充分地避免暫存器衝突導致的流水線阻塞。 對程式碼調整和流水線的時空圖如圖8所示。
調整之後,T1~T5是5個單獨的時鐘週期,T6~T13是一個迴圈,同樣在T14的時候BNE指令在寫LR的同時,迴圈的第一條指令開始取指,所以總的指令週期數為5+10×10+2×9+2=125。
通過兩段程式碼的比較可看出:調整之前整個拷貝過程總共使用了244個時鐘週期,調整了迴圈內指令的順序後,總共使用了125個時鐘週期就完成了同樣的工作,時鐘週期減少了119個,縮短了119/244=48.8%,效率提升十分明顯。 程式碼優化前後執行週期數對比的情況如表1所列。
因此流水線的優化問題主要應從兩方面考慮: ①通過合併迴圈等方式減少分支指令的個數,從而減少流水線的浪費; ②通過交換指令的順序,避免暫存器衝突造成的流水線停滯。4 結 論流水線技術提高了處理器的並行性,與序列CPU相比大大提高了處理器效能。通過調節指令序列的方法又能夠有效地避免流水線衝突的發生,從而提高了流水線的執行效率。因此如何採用智慧演算法進行指令序列的自動調節以提高流水線的效率和進一步提高處理器的並行性將是以後研究的主要方向。