深刻淺出計算機組成原理學習筆記:第十九講

1、引子

上一講,咱們講解了時鐘信號是怎麼實現的,以及怎麼利用這個時鐘信號,來控制數據的讀寫,可使得咱們能把須要的數據「存儲」下來。那麼,這一講,咱們要讓計算機「自動」跑起來。性能優化

經過一個時鐘信號,咱們能夠實現計數器,這個會成爲咱們的PC寄存器。而後,咱們還須要一個可以幫咱們在內存裏面尋找指定數據地址的譯碼器,以及解析讀取到的機器指令的譯碼器。
這樣,咱們就能把全部學習到的硬件組件串聯起來,變成一個CPU,實現咱們在計算機指令的執行部分的運行步驟。性能

2、PC寄存器所須要的計數器

咱們常說的PC寄存器,還有個名字叫程序計數器。下面咱們就來看看,它爲何叫做程序計數器。學習

有了時鐘信號,咱們能夠提供定時的輸入;有了D型觸發器,咱們能夠在時鐘信號控制的時間點寫入數據。咱們把這兩個功能組合起來,就能夠實現一個自動的計數器了。優化

加法器的兩個輸入,一個始終設置成1,另一個來自於一個D型觸發器A。咱們把加法器的輸出結果,寫到這個D型觸發器A裏面。因而,D型觸發器裏面的數據就會spa

在固定的時鐘信號爲1的時候更新一次。設計

 

這樣,咱們就有了一個每過一個時鐘週期,就能固定自增1的自動計數器了。這個自動計數器,能夠拿來當咱們的PC寄存器。事實上,PC寄存器的這個PC,
英文就是Program Counter,也就是 程序計數器的意思。3d

每次自增以後,咱們能夠去對應的D型觸發器裏面取值,這也是咱們下一條須要運行指令的地址。前面第5講咱們講過,
同一個程序的指令應該要順序地存放在內存裏面。這裏就和前面對應上了,順序地存放指令,就是爲了讓咱們經過程序計數器就能定時地不斷執行新指令。code

加法計數、內存取值,乃至後面的命令執行,最終其實都是由咱們一開始講的時鐘信號,來控制執行時間點和前後順序的,這也是咱們須要時序電路最核心的緣由。blog

在最簡單的狀況下,咱們須要讓每一條指令,從程序計數,到獲取指令、執行指令,都在一個時鐘週期內完成。若是PC寄存器自增地太快,程序就會出錯。
由於前一次的運算結果尚未寫回到對應的寄存器裏面的時候,後面一條指令已經開始讀取裏面的數據來作下一次計算了。這個時候,若是咱們的指令使用一樣的寄
存器,前一條指令的計算就會沒有效果,計算結果就錯了。內存

在這種設計下,咱們須要在一個時鐘週期裏,確保執行完一條最複雜的CPU指令,也就是耗時最長的一條CPU指令。這樣的CPU設計,咱們稱之爲 單指令週期處理器(Single Cycle Processor)。

很顯然,這樣的設計有點兒浪費。由於即使只調用一條很是簡單的指令,咱們也須要等待整個時鐘週期的時間走完,才能執行下一條指令。在後面章節裏咱們會講到,經過流水線技術進行性能優化,能夠減小須要等待的時間,這裏咱們暫且說到這裏。

3、讀寫數據所須要的譯碼器

如今,咱們的數據可以存儲在D型觸發器裏了。若是咱們把不少個D型觸發器放在一塊兒,就能夠造成一塊很大的存儲空間,甚至能夠當成一塊內存來用。像我如今手頭這臺電腦,
有16G內存。那咱們怎麼才能知道,寫入和讀取的數據,是在這麼大的內存的哪幾個比特呢?

因而,咱們就須要有一個電路,來完成「尋址」的工做。這個「尋址」電路,就是咱們接下來要講的譯碼器。

在如今實際使用的計算機裏面,內存所使用的DRAM,並非經過上面的D型觸發器來實現的,而是使用了一種CMOS芯片來實現的。不過,這並不影響咱們從基礎原理方面來理解譯碼器。
在這裏,咱們仍是能夠把內存芯片,當成是不少個連在一塊兒的D型觸發器來實現的。

若是把「尋址」這件事情退化到最簡單的狀況,就是在兩個地址中,去選擇一個地址。這樣的電路,咱們叫做 2-1選擇器。我把它的電路實現畫在了這裏。

咱們經過一個反相器、兩個與門和一個或門,就能夠實現一個2-1選擇器。經過控制反相器的輸入是0仍是1,可以決定對應的輸出信號,是和地址A,仍是地址B的輸入信號一致。

一個反向器只能有0和1這樣兩個狀態,因此咱們只能從兩個地址中選擇一個。若是輸入的信號有三個不一樣的開關,咱們就能從$2^3$,也就是8個地址中選擇一個了。這樣的電路,咱們就叫 3-8譯碼。現代的計算機,若是CPU是64位的,就意味着咱們的尋址空間也是$2^{64}$,那麼咱們就須要一個有64個開關的譯碼器。

 

因此說,其實譯碼器的本質,就是從輸入的多個位的信號中,根據必定的開關和電路組合,選擇出本身想要的信號。除了可以進行「尋址」以外,咱們還能夠把對應的須要運行的指令碼,一樣經過譯碼器,找出咱們

指望執行的指令,也就是在以前咱們講到過的opcode,以及後面對應的操做數或者寄存器地址。只是,這樣的「譯碼器」,比起2-1選擇器和3-8譯碼器,要複雜的多。

4、創建數據通路,構造一個最簡單的CPU

一、怎麼把這些零件組合起來

D觸發器、自動計數以及譯碼器,再加上一個咱們以前說過的ALU,咱們就湊齊了一個拼裝一個CPU必需要的零件了。下面,咱們就來看一看,怎麼把這些零件組合起來,才能實現指令執行和算術邏輯計算的CPU。

1. 首先,咱們有一個自動計數器。這個自動計數器會隨着時鐘主頻不斷地自增,來做爲咱們的PC寄存器。
2. 在這個自動計數器的後面,咱們連上一個譯碼器。譯碼器還要同時連着咱們經過大量的D觸發器組成的內存。
3. 自動計數器會隨着時鐘主頻不斷自增,從譯碼器當中,找到對應的計數器所表示的內存地址,而後讀取出裏面的CPU指令。
4. 讀取出來的CPU指令會經過咱們的CPU時鐘的控制,寫入到一個由D觸發器組成的寄存器,也就是指令寄存器當中。
5. 在指令寄存器後面,咱們能夠再跟一個譯碼器。這個譯碼器再也不是用來尋址的了,而是把咱們拿到的指令,解析成opcode和對應的操做數。
6. 當咱們拿到對應的opcode和操做數,對應的輸出線路就要鏈接ALU,開始進行各類算術和邏輯運算。對應的計算結果,則會再寫回到D觸發器組成的寄存器或者內存當中。

這樣的一個完整的通路,也就完成了咱們的CPU的一條指令的執行過程。在這個過程當中,你會發現這樣幾個有意思的問題。

二、第一個有意思的問題

是咱們以前在第6講講過的程序跳轉所使用的條件碼寄存器。那時,講計算機的指令執行的時候,咱們說高級語言中的if…else,實際上是變成了一條cmp指令和一條jmp指令。
cmp指令是在進行對應的比較,比較的結果會更新到條件碼寄存器當中。jmp指令則是根據條件碼寄存器當中的標誌位,來決定是否進行跳轉以及跳轉到什麼地址。

不知道你當時看到這個知識點的時候,有沒有一些疑惑,爲何咱們的if…else會變成這樣兩條指令,而不是設計成一個複雜的電路,變成一條指令?到這裏,咱們就能夠解釋了。
這樣分紅兩個指令實現,徹底匹配好了咱們在電路層面,「譯碼-執行-更新寄存器「這樣的步驟。

cmp指令的執行結果放到了條件碼寄存器裏面,咱們的條件跳轉指令也是在ALU層面執行的,而不是在控制器裏面執行的。這樣的實現方式在電路層面很是直觀,咱們不須要一個很是複雜的電路,
就能實現if…else的功能。

三、第二個有意思的問題

是關於咱們在第17講裏講到的指令週期、CPU週期和時鐘週期的差別。在上面的抽象的邏輯模型中,你很容易發現,咱們執行一條指令,其實能夠不放在一個時鐘週期裏面,
能夠直接拆分到多個時鐘週期。

咱們能夠在一個時鐘週期裏面,去自增PC寄存器的值,也就是指令對應的內存地址。而後,咱們要根據這個地址從D觸發器裏面讀取指令,這個仍是能夠在剛纔那個時鐘週期內。
可是對應的指令寫入到指令寄存器,咱們能夠放在一個新的時鐘週期裏面。指令譯碼給到ALU以後的計算結果,要寫回到寄存器,又能夠放到另外一個新的時鐘週期。因此,執行一條計算機指令,

其實能夠拆分到不少個時鐘週期,而不是必須使用單指令週期處理器的設計。

由於從內存裏面讀取指令時間很長,因此若是使用單指令週期處理器,就意味着咱們的指令都要去等待一些慢速的操做。這些不一樣指令執行速度的差別,也正是計算機指令有指令週期、
CPU週期和時鐘週期之分的緣由。所以,現代咱們優化CPU的性能時,用的CPU都不是單指令週期處理器,而是經過流水線、分支預測等技術,來實如今一個週期裏同時執行多個指令。

5、總結延伸

好了,今天咱們講完了,怎麼經過鏈接不一樣功能的電路,實現出一個完整的CPU。

咱們能夠經過自動計數器的電路,來實現一個PC寄存器,不斷生成下一條要執行的計算機指令的內存地址。而後經過譯碼器,從內存裏面讀出對應的指令,
寫入到D觸發器實現的指令寄存器中。再經過另一個譯碼器,把它解析成咱們須要執行的指令和操做數的地址。這些電路,組成了咱們計算機五大組成部分裏面的控制器。

咱們把opcode和對應的操做數,發送給ALU進行計算,獲得計算結果,再寫回到寄存器以及內存裏面來,這個就是咱們計算機五大組成部分裏面的運算器。

咱們的時鐘信號,則提供了協調這樣一條條指令的執行時間和前後順序的機制。一樣的,這也帶來了一個挑戰,那就是單指令週期處理器去執行一條指令的時間太長了。而這個挑戰,也是咱們接下來的幾講裏要解答的問題。

相關文章
相關標籤/搜索