《深入理解計算機系統》|處理器體系結構

《深入理解計算機系統》|處理器體系結構

img

目錄

學習事物是怎樣工作的有其內在價值:處理器是如何工作的對於我們普通人來說一直是個祕密,我們將從零開始構建一個流水線處理器,爲了實現這一處理器的軟硬件,我們有大量的前提知識要學習,包括:指令系統、硬件設計背景知識(hcl)、以及流水線的通用原理。學習完這些內容以後我們纔開始YY一個我們自己的86處理器。

本章內容


※ YY一個指令集Y86:各種狀態、指令集、編碼、編程規範、異常處理;

※數字硬件設計背景:處理器的基本構件,如何連接操作,介紹hcl語言;

※流水線原理,如何實現高效的五個步驟;如何處理冒險與衝突;

※開始實現我們自己的Y86;

筆記


一、基礎知識部分

1、介紹一個精簡的Y86指令集


①狀態碼

img

​ 狀態碼指明程序是否正常,程序可以訪問和修改:程序寄存器、條件碼、PC和存儲器

②所支持的指令

img

​ 長度:1-6字節,一條普通的指令包含:指令指示符+寄存器指示符+四字節常數

說明:

​ 1] 字段 fn 指明是某個整數操作:OPL、數據移動條件:cmovXX、分支條件:jXX;

​ 2] 圖中最後的pushl、popl指明不需要訪問任何寄存器0xF表示;

​ 3] xxmovl中:i代表立即數,r代表寄存器,m代表存儲器;

​ 4] OPL代表的是:add sub and xor;jXX代表:jmp、jle、jl、je、jne、jge、jg。

【疑惑:不允許:存儲器——存儲器 ;立即數——存儲器 爲什麼?】

③一條普通指令的編碼:

img

​ OPL指令有相同的code編碼6,不同功能編碼function區別不同操作

其他具體的編碼如下:

img

​ 整數、分支和數據傳送操作

根據功能進行最優化的存儲方式,比如rrmovl與條件傳送有相同的code編碼,這是因爲其行爲相當於無條件傳送。

!我們還需要訪問寄存器,爲了訪問的便利我們給寄存器編號,統一存放在CPU的一個寄存器文件中。就如學生時代的學號一樣,唯一、明確,也像收監的犯罪嫌疑人,你從入獄的那一天起將沒有名字,沒有身份,只是一個簡化的號碼。

img

​ 寄存器編號:esp4號,ebp5號,F代表無寄存器

舉例說明:rmmovl %esp , 0x12345(%edx)

​ rmmovl ——>4 0

​ esp|edx—③—>4 2

​ 0x12345——>00,01,23,45(小端法存儲)

合成到最後的指令就是:[40] [42] [45] [23] [01] [00]

任何一個指令序列都是一個唯一的編碼

④異常

img

​ 描述整體狀態

狀態碼如下:

img

​ 我們簡單的在異常條件下停止執行

⑤我們寫一段代碼試一試

img

​ c代碼

翻譯成x86和y86彙編形式,基本上沒什麼不同

img

(特別注意:pushl 將棧指針esp減去4,並將內容寫入存儲器中。當我們執行push esp時,我們約定:首先雅鹿esp的原始值,然後壓入減去4的esp的值)

2、邏輯設計和硬件控制語言


我們將會學到:計算對位進行組合的邏輯;存儲位的存儲原理和更新時鐘信號三部分內容。

① 對單個爲進行操作:邏輯門

img

​ 與門,或門,非門

② 組合邏輯用HCL表示:一個邏輯門肯定實現不了很多功能,我們來組合一下

用於檢測兩個Bit是否相等:

img

​ eq = (a && b) || (!a && !b)

當 a = b = 0時:上與邏輯爲0,下與邏輯爲1 或邏輯輸出eq爲1;

當a = b = 1時:上與邏輯爲1,下與邏輯爲0 或邏輯輸出eq爲1;

多路複用器:根據s的值選擇是輸出a或者b

img

​ out = (s && a) || (!s && b);

當 s = 0時,上與爲b, 下與爲0,或邏輯輸出out = b;

當 s = 1時, 上與爲0, 下與爲a,或邏輯輸入out = a;

四路複用器:

img

​ 根據s1和s0組合,選擇abcd其中一個

img

​ hcl表示圖

字級組合電路:單個的bit位並沒太大用途

img

​ 字級組合電路:用32個Equal電路組合而成

多路複用組合電路:使用32個MUX組合而成,只是非門是統一的一個

img

​ 多路複用組合電路

算術邏輯單元:ALU

img

​ 根據輸入設置會執行不同的邏輯運算中的一種

③ 集合關係

在處理器設計中,很多時候需要將一個信號與許多可能匹配的信號做比較,以此來檢驗正在處理的信號是否屬於某一類指令代碼;

img

​ 判斷是否在集合中

img

​ 結果在2,3中s1 = 1,結果在1,3中s0 = 1

④ 存儲器和時鐘:存儲原理(組合電路本身不能存儲信息,只是一個時間序列電路)

img

​ 更新週期將值放入存儲器中

分類:

1] 時鐘存儲器(寄存器):存儲單個位或字;

2] 隨機訪問存儲器(存儲器):存儲多個字;(虛擬存儲系統,寄存器文件,)

硬件寄存器和程序寄存器的區別:

​ 硬件寄存器:在硬件中寄存器直接將輸入和輸出連接到電路的其他部分;

​ 程序寄存器:CPU中位數不多的可尋址的寄存器,地址就是寄存器ID。

a.硬件寄存器:當時鍾信號處於高頻上升階段時,纔將輸入的信號加載

img

​ 硬件寄存器:保存cc、pc、stat值

b.寄存器文件

img

​ 寄存器文件

有兩個讀:A、B端口,和一個寫:W端口。允許同時進行多個讀寫操作,可以同時讀兩個寄存器和寫一個寄存器的值。srcX、desW代表地址,valX、valW代表要數據。如我們要訪問3號寄存器ebx的值,就將srcA=3,然後valA就是要訪問的數據。

c.隨機訪問存儲器

img

​ 隨機訪問存儲器

假如我們要訪問一個地址address上的數據,就將該地址傳入address中,同時設置write=0,那麼在data out上的數據就是我們要訪問的值了。

3 流水線通用原理


以自動化洗車設備爲例,車子需要按照一定的速度通過流水線,增加了一部分處理量。也就是不用等前面的車子洗完,就可以開入另一輛車子了;但這個系統有時候也會增加延遲,比如你只需要給車子打蠟,但也必須要經過噴水、抹乾階段。

①未加入流水線的系統:

img

​ 組合邏輯花了:300ps,處理卻只有20ps

②加入流水線的:

img

​ 分成三個階段,當指令I1進入B的時候,I2就可以進入A以此類推

通過將指令分成了3個階段,我經過一個120ps週期,每條指令就行進下一個階段

③流水線操作詳細說明:

img

​ 三個階段流水線時序

說明:詳細說明240-360的時鐘週期的故事

1] 點①時鐘開始上升之前(239):階段A中計算的指令I2已經到達第一個流水線寄存器的輸入,圖中藍色區域表示。但是該流水線寄存器Reg的值仍然是I1中的深灰色區域;指令I1在階段B中計算的值已經到達第二個流水線流水線寄存器的輸入Comb logic B,深灰色表示;

2] 點②時鐘開始進入上升階段(241):兩個組合邏輯輸入:A和B,將結果放入到流水線寄存器中,形成圖2的形式。藍色Reg和深灰色Reg,並將組合邏輯A設置成發起指令I3計算;

3] 點 ③階段信號開始傳播,信號通過不同的速率通過各個不同的部分;

4] 點④360來到之前,指令I3完成組合邏輯A處的加載,形成淺灰色區域。

img

​ 流水線操作的一個時鐘週期

④流水線的侷限性:

1] 不一致的劃分:由於階段的延遲並不一樣,這樣空閒的空間就增加了延遲;

2] 流水線過深,收益下降;

⑤帶反饋的流水線系統:許多指令前後相關,如何建立帶反饋的指令

二、從零開始構建我們的Y86處理器


1、一個Y86的順序實現(簡易方式)

爲了要實現一個通用的框架,我們通常要找到這個框架的層次結構,使得許多不同的指令可以共享相同的硬件,這是降低複雜度的一個有效的方法。

img

通用框架結構

①跟蹤一塊指令序列的執行:

img

​ Y86指令序列

②以 subl %edx, %ebx爲例:

img

③SEQ硬件結構圖:

img

​ seq抽象視圖

(注:爲什麼是逆序從下往上寫的?我們以後講流水線的時候再講解。)

④SEQ的時間和執行順序:

一條重要的原則是:處理器從來不需要爲了完成一條指令的執行而去讀該指令更新了的狀態。

比如我們之前講到的push %esp指令,如果是分步執行,先將esp-4,然後將更新後的值作爲寫地址效率就太低了。我們的做法是在執行階段計算出valE的值,然後在訪存和寫會階段同時完成更新寄存器和存儲器的操作。

img

​ push指令的三個階段

我們再來看一段代碼:

img

​ 講解SEQ時序

我們重點來看一下,第3和第4條指令的執行:

img

​ 執行序列

我們來簡單的講解一下執行的過程:

1] 在時鐘週期3開始的時候點①狀態元素保存的是週期2執行irmovl時的更新後的狀態,用淺灰色表示。點②:隨着時鐘週期開始上升時,地址0x00c載入pc中,這樣就取出了addl指令,值沿着Combinational Logic流動,充滿了淺藍色區域。在這個時候ebx就是加了以後的0x300新值,以及pc的新值0x00e。但是指令的狀態仍然保留的是irmovl指令設置的值。

2] 時鐘週期4:點③開始的時候,會更新程序計數器、寄存器文件、和條件碼寄存器。也就是addl更新的狀態。同樣的會取出je指令,用深灰表示,ZF=0不會選擇分支。在④的時候,pc產生新值0x013,Combinational Logic已經被更新過,但是狀態還是保持的是addl指令的設置的值。

img

我們再重申一下原則:通過時鐘週期來控制元素的更新,通過組合邏輯來傳播,每次時鐘週期由低到高時,處理器開始執行一條新指令。處理器從來不需要爲了完成一條指令的執行而去讀該指令更新了的狀態。

⑤Seq階段的實現:

1] 取指階段

img

​ 以PC爲起始地址,從指令存儲器中讀出6個字節

說明:第一個字節爲Split,字節0標號爲:icode和ifun;1-5字節爲Align:寄存器指示符和常數字的組合。

2] 譯碼和寫回階段:這兩個階段都需要訪問寄存器文件

img

seq的譯碼和寫回階段

同時支持兩個讀,A、B;和兩個寫:E、M;

3] 執行階段

img

​ 執行階段:根據ALU的值設置條件碼寄存器,檢測條件碼的值判斷是否選擇分支

根據ALU fun信號設置是否進行,加減乘除操作。ALU的輸出就是valE

4] 訪存階段

img

​ 訪存階段:讀或寫存儲器

5] 更新PC階段

img

​ 根據指令代碼和分支標誌,從valC valM和valP中選出下一個pc的值

2.Y86的流水線實現


我們說過,我們的目的是建立一個流水線化的處理器Y86,學了這麼久的基礎知識,也建立了一個簡化的Seq模型,我們終於可以開始我們的內容了,首先我們來優化一下簡易設計中的seq,我們稱之爲seq+:

①SEQ+:重新安排計算pc階段

SEQ+中沒有單獨的硬件寄存器來存放pc,而是通過pIconde、pCnd等寄存器計算pc的值。

設計原則:只要處理器能夠正確的執行機器語言,我們不需要程序猿可見狀態進行編碼,只要能產生正確的值就可以了。

img

​ 將pc移動到最開始的階段

詳細的seq+圖如下:

img

​ 將pc從時鐘週期結束移動到了開始,這樣更適合於流水線

②插入流水線寄存器的pipe-處理器結構:

img

​ pipe-硬件結構,我們創建了5階段流水線

說明:圖中以深藍色區域表示的就是我們加入的5個流水線寄存器,白色方塊代表不同的字段;

F : 保存pc預測值;

D :位於取指和譯碼之間,保存最新的指令信息,即將由譯碼階段處理;

E :位於譯碼和執行之間,保存最新譯碼指令和從寄存器讀出的值,即將由執行階段處理;

M :位於執行和訪存之間,保存最新執行指令的結果,條件分支和分支目標,即將由訪存處理;

W :位於訪存和反饋之間,提供給寄存器文件寫,完成ret指令,向pc提供返回地址。

③ 對信號進行重新排列和標號

在pipe-中有4個標號爲stat的白色區域,就是不同指令的狀態碼:D_stat、E_stat、M_stat、W_stat來區分。而小寫的:f、d、e、m、w指的是流水階段。

④ 預測一下一個pc:除了分支和ret指令外,我們基本上能夠用valC和valP的值來預測下一條指令的地址,這樣就可以通過之前學到的流水線技術使得每個週期執行一條指令。

⑤ 流水線的冒險和處理方法

什麼是流水線的冒險?一條指令更新後面指令會用到的值。

img

​ 數據冒險

當irmovl $3, %eax在第六個時鐘週期的時候,寫回階段eax還未得到正確的值3,而流水線的系統中,addl %edx, %eax已經需要使用eax的值,這時侯得到的就是錯誤的值。

**冒險的分類:**1)數據冒險;2)控制冒險;3)加載\使用數據冒險

我們之前講到流水線的反饋中,提到過如果兩條相鄰數據存在關聯該如何處理成爲了一個問題。特別是在使用流水線技術的情況下,如果一條指令要修改一個寄存器的內容,而下一條指令又剛剛需要引用該處的內容。如何使得兩條指令執行正確。

方法一:暫停

將指令阻滯在譯碼階段,相當於加入一條nop指令,直到獲得正確的值,才讓其他指令繼續執行。優點是實現容易,缺點是性能不佳

方法二:轉發

img

​ 通過使用狀態碼保存的值,實現旁路的轉發

圖中可以看出,我們不是在被動的等待irmovl執行完畢,而是在addl指令需要用到eax值的時候,我們將irmovl的W階段的中間值,W_valE=3轉發到addl指令中去,賦值給eax。

5個用作源的有:e_valE、m_valM、M_valE、W_valM、W_valE;兩個目的:valA、valB

1526541639756

​ 流水線化的最終實現——PIPE的硬件結構

有一類比較特殊的數據冒險:加載\使用數據冒險,我們特別講一下?

img

Load 、 Use 數據冒險

上面的兩條指令,我們具體來看一下流水線的執行過程:

img

​ 加載使用數據冒險

我們執行0x018指令,要在第八個時鐘週期的時候才能獲得eax的值,而0x01e指令在第七個時鐘週期就需要這個eax,我們不可能將這個值從第八個週期傳回第七個週期。就像不能穿越時間線回到過去一樣。遇到這種情況我們的處理方式是:使用暫停和轉發相結合的方法,確切的講就是暫停addl執行的一個時鐘週期,使得在週期8的時候實現轉發。

⑥ 異常處理

**異常分爲:**halt指令、有非法指令和功能碼組合的指令、訪問非法地址

處理方法:有多條指令引起異常,由流水線最深的指令優先級最高

​ 多條分支中有異常,取消預測指令

​ 出現異常,根據狀態碼的stat值,禁止其他指令更新程序狀態

⑦ PIPE各個階段的實現:

1] PC選擇和取指階段

img

​ 選擇和取指邏輯

PC選擇器必須要選擇出正確的pc值,一般來說有三種方式可選:當預測錯誤分支進入訪存,選擇M_valA中的valP;當ret指令進入寫回階段時,選擇W _valM;其他情況下選擇F_predPC。

2] 譯碼和寫回階段:

img

​ 譯碼寫回

疑問:對於轉發邏輯和不同的轉發源還不明白;對Sel+Fwn的具體功能不明確

3] 執行階段:

img

​ 同SEQ中相似

4] 訪存階段

img

⑧ 流水線控制邏輯

1]特殊情況的處理

ret指令實際的處理過程是在取指階段反覆的取出ret指令後面的指令,在譯碼階段插入氣泡;

當分支結果還未計算出來的時候,保持預測指令執行在FD階段,這樣可以防止,如果預測錯誤,預測指令不會修改程序狀態。如果決定不執行分支,取消指令的執行不會帶來錯誤的影響;實現的方法是根據stat的值:禁止執行階段中的指令設置條件碼;向存儲階段插入氣魄,以禁止寫入;當寫回階段有異常的時候,暫停寫回。

2]流水線的控制機制:加入氣泡和暫停

img

​ 加入stall、bubble

當暫停stall=1的時候,狀態保持先前的值不變;

當bubble=1的時候,用nop覆蓋當前的狀態

3]控制條件的組合

img

​ 兩種特殊情況的組合

我們需要處理的情況爲組合B:加載指令設置寄存器esp的值,而ret指令將esp用作源操作數,因爲它必須從棧中彈出返回地址,流水線控制應將ret指令阻滯在譯碼階段。

(注:系統分析的重要性,僅僅運行正確其實並不可靠)

4]最終控制模型:

img

​ 控制邏輯全

⑨ 未完成的工作:與存儲器的接口和多週期指令。

文章轉自:《深入理解計算機系統》|處理器體系結構

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