計算機系統要素,從零開始構建現代計算機(nand2tetris)
如果完成了本書所有的項目 你將會獲得以下成就
- 構建出一臺計算機(在模擬器上運行)
- 實現一門語言和相應的語言標準庫
- 實現一個簡單的編譯器
而且,這本書的門檻非常低,只要你能熟練運用一門編程語言即可。本課程綜合了數字電路,計算機組成原理,計算機體系架構,操作系統,編譯原理,數據結構等的主要內容,搭建了計算機平臺的構建的框架,並未深入細節,如果需要了解細節,可由本書作爲主線,逐步完善的知識體系。
QQ交流羣(含資料):289682057
課程連接
項目地址Github
本章要實現的內容
- Memory:內存,包括數據內存和指令內存,屏幕內存映像和鍵盤內存映像
- CPU:包含A寄存器,D寄存器,ALU,PC程序計數器
- Computer:完整的一個計算機平臺。運行在仿真平臺上
實現總結
Memory:
輸入管腳:in[16], load, address[15]
輸出管腳:out[16]
Memory芯片主要由三個底層芯片構建:RAM16K,Screen,KeyBoard。同時我們必須通過這三個底層芯片來實現一個統一的邏輯地址空間,這個空間從地址0到24567。構建這個連續的地址空間的方法我們可以參考之前第三章由小RAM構建大RAM的方法。
內存的功能首先能夠根據address選定需要進行操作的單元。
然後將load信號給指定的內存單元。根據load信號判斷是進行寫入還是繼續保持。
下面進行地址連線:參考自計算機組成原理(注意此地址只有15位)
RAM16K的地址空間:000 0000 0000 0000 ~ 011 1111 1111 1111
屏幕內存映像的地址空間(8K):100 0000 0000 0000 ~ 101 1111 1111 1111
鍵盤內存影響的地址空間:110000000000000
1、首先根據地址進行判斷,應該將控制信號發送給哪個地址空間。可以使用DMux實現
根據第15位進行二選一,可以選出RAM和映像,然後再對選出的結果進行二選一,根據第14位進行選擇可以選出屏幕和鍵盤。由於所給出的地址空間不會超過110000000000000,所以我們只需要進行一次判斷就可以了,而不用考慮後面13位的判斷。
2、然後將控制信號,輸入數據和片內選擇地址給各自的地址空間即可
Screen和Keyboard芯片都是內置好的,因此直接調用接口即可。實際上我們也可以根據第三章的方法構建自己的Screen和Keyboard
CPU
輸入管腳:inM[16], instruction[16], reset
輸出管腳:outM[16], writeM, addressM[15], pc[15]
CPU實現的一種推薦方案:
1、回顧一下第四章的指令格式:
A-指令:。MSB0,其餘15位表示地址值
C-指令:。MSB爲1,接着的兩位無效。a位域控制與D進行計算的是A還是M,c位域是計算操作的控制,控制是否將ALU的計算結果存在A中,控制是否將ALU的計算結果存在D中,控制是否將ALU的計算結果存在M中,是指示調轉的控制。
2、解碼指令
如果是A指令,那麼要將地址加載到A寄存器中,如果是C-指令,則考慮,是否需要將ALU的計算結果保存在A寄存器中。不妨暫時將第一個Mux的控制位記爲,將A寄存器的控制位記作。那麼我們可以得到以下真值表:
[15] | |||
---|---|---|---|
0 | 0 | 1 | 1 |
0 | 1 | 1 | 1 |
1 | 0 | 0 | 0 |
1 | 1 | 0 | 1 |
由真值表我們可以得到控制位的公式:。
對於A-指令以上的工作就已經足夠了。而對於C-指令我們還需要做其他的工作。
3、C-指令的解碼
C指令的位已經被解析完了。接下來從左向右開始解碼。是控制選擇A/M的控制位,所以它應該在與指令最高位取與後給第二個Mux。是控制計算函數的,所以它們應該給ALU的控制位,注意要與指令最高位取與。是控制計算結果是否保存在D中的,所以它與指令最高位取與後作爲控制信號給D寄存器,是控制計算結果是否保存在M中的,所以它作爲輸出與指令最高位取與後給writeM。接下來是控制跳轉的,總體上來看,只有兩種現象,一種是順序執行,即PC加一,另一種是跳轉到地址爲A中的地址的單元。根據課本給出的編碼:
那麼究竟是否需要跳轉要根據ALU的計算結果進行判斷,ALU有兩個特別的輸出信號:zr(當計算結果等於0時爲1),ng(當計算結果小於零時爲1)。所以我們可以推出(當計算結果大於零時爲1)。結合jump域和ALU的輸出結果,可以得到如下真值表:
load | inc | |
---|---|---|
0 | 0 | 1 |
1 | 1 | 0 |
4、完成連線
這一步很簡單,不再介紹
關於CPU的構建,課程有很詳細的介紹,參考課程即可。個人覺得在這個過程中,最困難的就是梳理控制邏輯,使用有限狀態機來梳理整個過程,更有利於深刻而清楚的理解CPU的工作過程,鑑於個人沒有學習過體系結構方面的內容,並且組成原理課程並未涉及到CPU的內容,所以上述內容難免有錯誤出現,望各位讀者不吝批評。
Computer
輸入管腳:reset
在構建這一部分的時候並沒有什麼複雜的邏輯,這就像,給了你CPU,硬盤,顯示屏,內存條,顯卡…等計算機組件,讓我們構建一個計算機。這樣看來,我們需要做的就是把他們按在主板上,並連上線就可以了。
階段總結
至此,就正式完成了一個簡單的計算機平臺,也可以說是個計算機芯片,也可以說是個模型機,儘管它是個模型機,但是根據這個模型機的構建原理,我們可以動手使用真正的芯片來構建自己的計算機平臺了。首先使用大量的原始芯片,比如Nand,DFF,我們可以構建出簡單的組件,比如選擇器,解碼器,寄存器,RAM,這四個分別是組合邏輯和時序邏輯的典型代表。接着,我們使用這些簡單組件來構建複雜的組件,構建CPU和Memory。並且,我們可以自己定義自己的指令編碼規則,然後在這些組件上測試指令。然後使用這些複雜的組件來構建我們自己的計算機,儘管它看起來一定非常醜陋,但是它的意義是非凡的,這意味着我們掌握了計算機的構建方式。我們可以在上面運行01組成的機器指令,這在外行看來一定是非常厲害的,儘管我們會認爲它還僅僅是個嬰兒。
在這個階段中,一開始是比較簡單的,只需要簡單的數據電路知識就可以完成芯片的構建,這個過程我充滿了疑惑,構建的這些芯片究竟有什麼作用?不過,很快這些疑惑就被解決了,在我構建完一個簡單的ALU之後,我才發現,這些芯片原來都有自己的重要價值。與或非門,就想是一些簡單的組件,在必要的時候起一些輔助的作用,不過大型的複雜的組合邏輯芯片都是基於這些簡單的門電路。而半加器之所以稱爲半加器,就是因爲它只完成了一半的加法,因爲它忽略了進位,當真正構建出來這些芯片,並使用它們的時候,才發現原來名字是這麼的直截了當,跟當初學習理論的時候感覺完全不一樣。另外就是全加器,它是ALU進行運算的關鍵。後來的時序邏輯是有些困難,不過看到這簡單的DFF,竟然能存儲一個位的數據,而寄存器竟然就是由這樣的一個個的DFF實現的,非常神奇。構建CPU的時候,遇到了很大的困難,分析課本上給出的實現圖,一直都沒有頭緒,嘗試了很多次,思路都很零散,沒有邏輯性,幾乎都快放棄了,後來在羣裏請教了一下前輩,得前輩的指導,我又看了一下配套的視頻,然後慢慢的從分析A-指令和C-指令開始梳理自己的思路,大概用了一個下午的時間,完成了CPU的構建,並通過了測試。信心倍增,而之後的Computer的構建是很簡單的,幾乎一氣呵成。到此,我可以說:如果我有足夠的芯片,我一定能構建出來一臺計算機!在接下來的階段裏,繼續加油!!