摘要:從全局來看,大多數計算機只是傳遞一堆布爾值,所以任何對布爾值友好的語言都可以完成這項工作。將模式應用于這些布爾值能夠幫助程序員獲得其含義,任何人都要做的最大決策是確定系統(tǒng)將使用哪種字節(jié)順序,并確保所有組件都以正確的順序在總線之間傳遞信息。
芯片的設計到底有多難?想要回答這個問題最好還是先自己實踐一下。最近,來自 BBC 的一名資深軟件工程師 Daniel Harper 使用 Go 語言成功模擬出了一個 CPU 的所有功能,并把自己的經歷寫成了博客,引起了人們的熱議。這篇文章也告訴我們:完整地了解計算機的工作原理是多么重要。
選自djhworld博客,作者:daniel harper,機器之心編譯,參與:杜偉、張倩、李澤南。
Daniel 的經歷在社交網絡上不僅被好奇的群眾點贊,也引發(fā)了大學芯片相關課程的學生和助教們的共鳴。如果你不知道 L1/L2 緩存的意義,認為自己沒有搞清楚英特爾、ARM 芯片上著名的 Meltdown、Spectre 漏洞的意義,現(xiàn)在是時候開始學習了。
讓我們看看 Daniel 是如何做到模擬 CPU 的:
幾個月前,我實在不理解計算機如何在后臺工作,也不清楚現(xiàn)代計算機的工作原理。之后,我讀了 J. Clark Scott 的書籍《But How Do I Know");
我對電路學知識的興趣不大,而這本書只是簡單概述了一些基礎知識,包括接線以及在沒有必備電氣工程知識的情況下位元如何在計算系統(tǒng)中移動。對我而言,從這本書中獲得的知識不多,所以必須親身實踐,并從不可避免的錯誤中吸取經驗教訓,這樣使我能夠有條理地用代碼編寫電路。
相關成果的 GitHub 地址為:https://github.com/djhworld/simple-computer
這臺簡單的計算機可以用來計算。
示例程序
這是一個相當整潔的小東西,CPU 代碼被實現(xiàn)為一個開閉的門,但它奏效了,我已經進行了測試,以此證明它能夠運行。
該程序操控鍵盤輸入,并將文本呈現(xiàn)給顯示器,其中使用了一套精心制作的字形作為專業(yè)字體,我將其命名為「Daniel Code Pro」。唯一作弊的一點是獲取鍵盤輸入并顯示輸出內容,為此我必須通過 GLFW 與外界通信,但剩余部分是模擬電路。
我甚至編寫了一個簡單的匯編程序,這令人大開眼界。這并不是完美的,實際上有點胡扯。但是,我了解到了其他人很多年前已經解決了的問題,并認為自己的這項工作更好。
為什么要做這個?
我曾看到一個 13 歲的孩子在 Minecraft 中做這項工作,所以等你用電報繼電器制作出一個真正的 CPU 時再來質問我吧!
我心中的計算模型還停留在計算機科學初級教科書的層面,并且驅動我在 2013 年所編寫的 Gameboy Emulator 的 CPU 與現(xiàn)今計算機運行的 CPU 完全不同。甚至可以說,模擬器只不過是一種狀態(tài)機(state machine),它沒有從邏輯門(logic gate)層面描述 CPU。僅使用 switch 語句即可以實現(xiàn)大多數 CPU 且能夠存儲寄存器狀態(tài)。
我不知道 L1/L2 緩存(cache)和 pipelining 是什么,也完全不確定自己是否理解 Meltdown 和 Spectre 漏洞論文,所以想要更深入地了解這些東西。一些人告訴我,他們正在優(yōu)化代碼以更好地利用 CPU 緩存,而我卻不知道如何驗證真假,只能選擇相信他們。我真的不確定 x86 指令是什么。我不了解人們如何能夠將工作交給 GPU 或 TPU 處理,也不清楚什么是 TPU,更不清楚如何使用這些 SIMD 指令。
但所有這一切都需要具有相關的基礎知識,所以我只有在閱讀相關書籍后才能對此有所了解。這意味著我需要回到基礎知識和原理上面,并從一些簡單的程序上手。《But How Do I Know");
功能強大的 Scott 計算機!可以運行的!
Scott 計算機是一個附有 256 字節(jié) RAM 的 8 位處理器,并通過 8 位系統(tǒng)總線連接。該計算機擁有 4 個通用寄存器,能夠執(zhí)行 17 個機器指令。一些人搭建了一個很酷的視覺模擬器(visual simulator),無法想象需要花費多長時間才能跟蹤全部的接線狀態(tài)!
組成 Scott CPU 的所有組件圖解。
《But How Do I Know");
我的開發(fā)之旅
開發(fā)過程實際上只是閱讀文本、查找圖表、然后嘗試使用通用編程語言代碼(而不是使用為集成電路開發(fā)而設計的代碼)來翻譯。
之所以用 Go 語言來寫,是因為我對 Go 了解一點。杠精們可能會說,我不信你沒有將時間花在學 VHDL、Verilog 或 LogSim 上,但我那時已經編寫好了我的位元、字節(jié)和 NAND,我陷得太深了。也許我接下來會學那些東西。
從全局來看,大多數計算機只是傳遞一堆布爾值,所以任何對布爾值友好的語言都可以完成這項工作。
將模式應用于這些布爾值能夠幫助程序員獲得其含義,任何人都要做的最大決策是確定系統(tǒng)將使用哪種字節(jié)順序(endianness),并確保所有組件都以正確的順序在總線之間傳遞信息。
這絕對是實現(xiàn)中隱藏的痛點之一。從偏移量上看,我選擇了較小的字節(jié)順序。但在測試 ALU 時,我就遇到麻煩了。我試圖找出為什么出來的數字是錯誤的。很多很多打印語句都發(fā)生在這個上面。
開發(fā)的確花了一些時間,大約是一兩個月的業(yè)余時間。但一旦成功搭建出 CPU 并用它執(zhí)行 2 + 2 = 5,我還是感到很欣慰。
書中討論了 I/O 特性,設計了一個簡單的鍵盤和顯示界面,這樣你就可以把東西放進機器或拿出來。我給自己設定了一個目標,那就是能夠在鍵盤上輸入一些東西,并在顯示器上顯示這些字母。
外設
在這里,外設使用的是適配模式,充當 CPU 和外部世界之間的硬件接口。這里并不難猜,肯定是軟件設計模式獲取靈感的地方。
I/O 適配器是如何連接到 GLFW 窗口的。
通過分離關注點,使用 GLFW 將鍵盤輸入的內容輸出到屏幕是非常簡單的過程。事實上我只是從模擬器中提取了大部分代碼并整形了一下,使用 go 通道作為進出機器的信號。
讓它跑起來
這可能是最難的一部分,至少也是最麻煩的。用如此有限的指令集編寫程序集真的很糟糕。使用我編寫的粗糙的匯編程序編寫程序集更糟糕,因為你怪不得別人。
最大的問題在于同時處理這 4 個寄存器并跟蹤它們,將它們作為臨時存儲存儲到內存中。在這個過程中,我記得 Gameboy CPU 有一個堆棧指針寄存器,這樣你就可以推送和彈出狀態(tài)。不幸的是,這臺電腦沒有這么奢侈,所以我主要是在定制的基礎上對內存里的東西進行移進移出操作。
我唯一花時間實現(xiàn)的偽指令是 CALL,以幫助調用函數。這可以讓你運行一個函數,然后在函數被調用后返回到該點。由于沒有堆棧,你只能調用一層的深度。
由于機器不支持中斷,為獲取鍵盤狀態(tài)等函數,你必須實現(xiàn)糟糕的輪詢代碼。書中的確提到了實現(xiàn)中斷的步驟,但那需要寫更多代碼。
無論如何,我最終編寫出了四個程序,其中多數程序使用一些共享代碼來繪制字體、獲取鍵盤輸入等。雖然與操作系統(tǒng)還有一定的距離,但它確實讓我意識到一個簡單的操作系統(tǒng)也可能提供一些服務。
但這其實并不容易,文本編寫程序最棘手的部分是計算出何時轉到新行,或當你按回車鍵時發(fā)生了什么。
main-getInput: CALL ROUTINE-io-pollKeyboard CALL ROUTINE-io-drawFontCharacter JMP main-getInput
上述文本編寫程序的主要循環(huán)。
我也沒有抽出時間來實現(xiàn)退格鍵或其他任何修改鍵。這讓我意識到制作文本編輯器需要做多少工作,這項工作可能是多么乏味。
反思
這個項目對我來說非常有趣,也很有收獲。在用匯編語言編程的過程中,我基本上放棄了底層的 NAND、AND 和 OR 門。我上升到了上面的抽象層。雖然我做的這個 CPU 很簡單,距離電腦里的 CPU 還很遠,但通過這個項目我學到了很多,如:
位元如何在使用總線的所有組件之間移動
一個簡單的 ALU 是如何工作的
一個簡單的 Fetch-Decode-Execute 循環(huán)是什么樣的
沒有堆棧指針寄存器的機器+堆棧的概念很糟糕
沒有中斷的機器很糟糕
匯編程序是什么、如何工作
外圍設備如何與一個簡單的 CPU 通信
簡單字體的工作原理和在顯示器上顯示它們的方法
一個簡單的操作系統(tǒng)會是什么樣子
相關課程
如果你對于芯片的工作原理非常有興趣,先上一些在線課程也是一個好方法。這一 Udacity 免費課程《高性能計算架構》源自佐治亞理工:
https://cn.udacity.com/course/high-performance-computer-architecture--ud007
原文地址:https://djhworld.github.io/post/2019/05/21/i-dont-know-how-cpus-work-so-i-simulated-one-in-code/
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/7018.html
摘要:從全局來看,大多數計算機只是傳遞一堆布爾值,所以任何對布爾值友好的語言都可以完成這項工作。將模式應用于這些布爾值能夠幫助程序員獲得其含義,任何人都要做的最大決策是確定系統(tǒng)將使用哪種字節(jié)順序,并確保所有組件都以正確的順序在總線之間傳遞信息。芯片的設計到底有多難?想要回答這個問題最好還是先自己實踐一下。最近,來自 BBC 的一名資深軟件工程師 Daniel Harper 使用 Go 語言成功模擬...
摘要:失敗重試自旋比如說,我上面用了個線程,對值進行加。我們都知道如果在線程安全的情況下,這個值最終的結果一定是為的。那就意味著每個線程都會對這個值實質地進行加。 前言 只有光頭才能變強 之前已經寫過多線程相關的文章了,有興趣的同學可以去了解一下: https://github.com/ZhongFuCheng3y/3y/blob/master/src/thread.md showImg(h...
摘要:故障注入為您的微服務注入故障以驗證集群性能由于導師和實驗室?guī)熜謧兊目蒲行枰?,本人專門以的模式設計了一個用于錯誤注入的微服務模塊。 故障注入 Sidecar——為您的微服務注入故障以驗證集群性能! 由于導師和實驗室?guī)熜謧兊目蒲行枰救藢iT以 Sidecar的模式設計了一個用于錯誤注入的微服務模塊。該模塊可以與任何微服務應用共同部署運行,為其模擬cpu、內存等錯誤。 本項目的 Githu...
摘要:故障注入為您的微服務注入故障以驗證集群性能由于導師和實驗室?guī)熜謧兊目蒲行枰救藢iT以的模式設計了一個用于錯誤注入的微服務模塊。 故障注入 Sidecar——為您的微服務注入故障以驗證集群性能! 由于導師和實驗室?guī)熜謧兊目蒲行枰救藢iT以 Sidecar的模式設計了一個用于錯誤注入的微服務模塊。該模塊可以與任何微服務應用共同部署運行,為其模擬cpu、內存等錯誤。 本項目的 Githu...
閱讀 1766·2023-04-26 01:41
閱讀 3072·2021-11-23 09:51
閱讀 2732·2021-10-09 09:43
閱讀 9018·2021-09-22 15:13
閱讀 2452·2021-09-07 09:59
閱讀 2623·2019-08-30 15:44
閱讀 1131·2019-08-30 12:45
閱讀 2615·2019-08-30 12:43