CPU Wiki: Sandy Bridge Microarchitecture 前端(下)

在這裏插入圖片描述
MSROM & Stack Engine
在X86指令中,有一些連複雜解碼器都認爲複雜的指令。這些指令會被翻譯成超過4條uops,它們是從microcode sequencer(MS) ROM 繞道譯碼的。此時,MSROM每週期會發射超過4條指令,直到microcode sequencer完成了工作。在此期間,譯碼器停止工作。
x86有這一個專門的stack machine 操作。像push,pop和call,ret這樣的指令,是工作在stack pointer(ESP)上的。如果沒有這樣專門的硬件,這樣的指令操作將會被髮送到後端的執行單元,使用通用的ALU計算,佔用了帶寬以及調度器和發射單元的資源。自從Pentium M之後,Intel就採納了Stack Engine的技術。Stack Engine 有這一組三個專門的累加器,用於實現更新棧的指令(可以每週期進行3次加法)。像push這樣的指令翻譯成store指令和將ESP-4的指令。此時的減法操作將會被Stack Engine完成。Stack Engine位於decoders的後面,監視uOps指令流。Stack Engine 將會抓住輸入的更新棧寄存器的操作。這可以更新棧指針的uops造成的流水線的負擔。換句話說,這相對於將這些操作放入流水線並通過執行單元計算,更加簡單更加快速。

New uOp cache & x86 tax
譯碼變長,不連續並且複雜的x86指令是一個複雜的工作。考慮性能和功耗,譯碼的代價也是非常昂貴的。因此,對流水線來說,最好就是不進行譯碼了,這恰恰就是Intel向Sandy Bridge中加入的最重要的功能。Sandy Bridge 引入了一個新的new uOp Cache 單元,可能更準確的應該叫做 Decode Stream Buffer(DSB)。micro-op cache的獨特在於其不僅可以大幅度的提高性能,也可以大幅的的降低功耗。
表面看來,uOP cache 被定位爲一個2級指令cache單元,是1級指令cache單元的子集。其獨特之處在於它所存儲的是譯碼之後的指令(uOPs)。儘管它與NetBurst的trace cache的大部分目標相同,二者的實現確實完全不同。考慮到它是如何增強了其餘的前端的功能,這點顯得尤爲真實。兩者機制背後的思想都是增加前端的帶寬,並降低對譯碼器的依賴。
Micro-op cache是由32組 8條cacheline 組成。每條cacheline最多保留6條uops,共計1536條uOps。這個Cache是在兩個線程之間共享的,並保留了指向micro sequencer ROM的指針。它也是虛擬地址尋址,是L1 指令cache的嚴格的子集。每條cacheline還包括其包含的uop數量和其長度。
在任何時間,core都是處理來自instruction stream的連續的32byte。同樣的,uOP cache也是基於32byte窗口。因此uOP cache可以基於LRU策略存儲或者放棄整個窗口。Intel將傳統的流水線成爲“legacy decode pipeline”。在首次迭代時,所有的指令都是經過“legacy decode pipeline”。一旦整個指令流窗口被譯碼並且發送到分配隊列,窗口的拷貝就被髮送到uOP cache。這是與所有其他操作同時發生的,因此這個功能沒有增加額外的流水線階段。後續的迭代,被緩存的已經解碼好的指令流就可以直接被髮送到分配隊列了,省卻了取指,預譯碼,和譯碼的階段,節省功耗,增加了吞吐量。這也是一個更短的流水線,latency也被減小了。
注意32byte的指令流窗口只能擴展到3條cacheline。這意味着每個窗口最多有18條uops被uop cache緩存。這個也就意味着一個32byte的窗口如果產生了超過18條uops,那麼就不會被分配到uOP cache中。將會不得不進入“legacy decode pipeline”。然而。這樣的場景是非常少見的,大多數的workload都可以從這個特性中受益。
uOP cache有着高於80%的命中率。在取指期間,分支預測器將會讀取uOPs cache 的tags。如果命中了cache,會可以每週期發送至多4條uops(可能包含了fused macro-ops)到 Instruction Decode Queue(IDQ), bypass了其他所有本該進行的預譯碼和譯碼。在其他週期內,其餘的前端完全被clock gated,因此降低了大量的功耗。儘管 legacy decode path工作在16byte取指窗口內,uOP cache沒有這樣的限制,可以發送最多4uOPs/cycle,對應着超過32byte的窗口。考慮到單個窗口可能包含18條uOPs,可能要花費5個週期才能讀完整條已經解碼完畢的指令流。儘管如此,uOPs cache可以提供連續的高帶寬的指令流。然而,legacy decode pipeline,被限制在16byte 取指窗口內,如果平均指令長度超過4byte,那麼將會是一個嚴重的瓶頸(無法達到4uop,無法使後端滿負荷工作)。
在這裏插入圖片描述
有趣的是uOPs cache只工作在滿窗口下,也就是整個32B的窗口的所有uOPs都被cache了。如果只是任何單部分的命中,那麼仍然需要通過“legacy decode pipeline”,彷彿沒有被cache過。不處理部分命中的選擇根植於特性效率。如果只是部分命中,輸出部分譯碼過的指令,那麼其餘的指令還需要經過“legacy decode pipeline”。這樣的機制不僅會增加複雜性,而且並不清楚可以獲益多少。
如前所述,uOPs cache根植於原始的NetBurst trace cache,尤其是考慮到它們相同的目標。但是它們也僅僅是目標相同。Sandy Bridge 中的micro-op cache 是一個輕量級的,有效地uOPs傳遞機制,可以在任何可能的時候都超過legacy pipeline的性能。這與trace cache不同,trace cache試圖有效地去取代整個前端,在trace cache不能處理的workload的情況下,表現較差,取指和譯碼都比較緩慢。考慮到trace cache代價巨大而且複雜(有着專門的 trace BTB單元),並且在上下文切換時,需要進行flush,而有着副作用。uOP cache則沒有這個缺點。trace cache也有着大量不必要的重複。比如NetBurst的trace cache多大12K uops,與 8KB-16KB的L1 cache的命中率接近。然而1.5K uOPs的命中率接近6KB 指令cache。這意味着存儲效率要提高了超過4倍。

歡迎關注我的公衆號《處理器與AI芯片》

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章