1, 簡介
中央處理器(Central Processing Unit,簡稱CPU)是一塊由超大規模的集成電路組成的運算和控制核心,主要功能是運行指令和處理數據?,F在CPU一般都比較小,基本上只有指甲蓋般大小。CPU從誕生到現在主要在兩個維度上做了很大的提升,一個是材料及工藝,另一個是設計思想。
我們先看第一個維度:材料及工藝。你可曾想過人類歷史上第一個計算機(主要就是CPU)有多大?據資料了解其大小為24.4米×2.4米,重達28噸,功耗為170kW,但是運算速度僅為每秒5000次的加法運算。人類第一個CPU之所以體積這么大,功耗這么高,是因為它使用了17840支電子管。隨著1947年貝爾實驗室的肖克利等人發明了鍺晶體管(又叫做三極管),人們可以用體積小、功耗低、開關速度快的晶體管替換體積大、功耗高、開關慢的電子管。晶體管是20世紀的一項重大發明,為集成電路的誕生做了堅實的鋪墊。
隨著20世紀中后期,半導體制造技術進步,使得集成電路成為可能。相對于使用各種分立電子組件組裝電路,集成電路可以把很大數量的微晶體管集成到一個小芯片上,這是一個巨大的進步。第一個集成電路是在1958年由杰克·基爾比完成的,它包括一個雙極性晶體管,三個電阻和一個電容器。1959年,仙童公司首先推出了采用光刻技術的平面型晶體管(如二極管、三極管、電阻和電容),而后1961年推出了平面型集成電路。理論上只要光刻工藝不斷提升,元器件的密度也會相應地提升。1965年時任仙童半導體實驗室主任的摩爾提出了摩爾定律:集成電路可容納的元器件數量,每18~24個月翻一番。
再看第二個維度:設計思想。其實,在第一個計算機誕生的時候,雖然采取了最先進的電子技術,但缺少設計思想上的指導,導致很多邏輯都是硬化在電路板上的。這會造成一旦修改程序,就要重新組裝電路板,這樣的編程效率很低。這時馮·諾依曼提出了一個至關重要的設計思路:計算機的邏輯結構,將軟硬件分離,要求CPU順序地從存儲器中取出指令和數據進行相應的計算,主要的思想:
二進制:程序、數據的最終形態都是二進制編碼、存儲在存儲器中,二進制編碼也是CPU能夠識別、執行的編碼;
指令、數據可存儲:指令序列和數據存在主(內)存儲器中,以便于CPU在工作時能夠高速地從存儲器中提取指令并加以分析和執行;
計算機組成:確定了計算機的五個基本組成部分,運算器、控制器、存儲器、輸入設備、輸出設備;
馮·諾依曼的結構框圖如下:
其實,馮·諾依曼體系結構也存在一些問題,但是人們并沒有完全拋棄這種體系結構,而是在這一系列問題上做了改進:
指令、數據公用內存:指令和數據都存儲在一個存儲器上,并且通過一個系統總線進行訪問。 當前主存的讀寫速度是跟不上cpu運行速度的,所以為了解決這個問題,在cpu和主存增加了高速緩存,并且在L1高速緩存上,還區分了指令緩存和數據緩存,并進一步提升系統總線的訪問速度。 另外,為了解決指令和數據共用系統總線帶來的速度慢的問題,又提出了哈佛架構,將指令和數據分別存放在不同的主存上,可以并行訪問,這提高了運行速度,但是結構復雜,不適合外部主存的擴展,所以哈佛結構并未得到廣泛應用;
指令順序指令:指令只能順序,在一個pipe上運行。 為了提升指令運行速度增加了,亂序執行、多級流水線、分支預測等功能;
在馮·諾依曼體系結構設計思想指導下,并伴隨著芯片在摩爾定律下的制作工藝提升,現在的CPU越來越強大,在功能、算力不斷提升的同時,功耗、面積也在不停的減少。 得益于芯片技術的發展,我們現在不僅有更輕便,容易攜帶的筆記本,還有各種方便攜帶的嵌入式產品使用,比如:智能手機、智能手表、藍牙耳機等。 可以預見,隨著技術的發展,后面將會有更豐富的產品出現,這無不彰顯了科學技術就是第一生產力。 接下來,我們重點關注當代CPU的工作原理,通過對CPU工作原理的了解,為工作中更好地進行功能開發、性能優化、功耗優化做鋪墊。
2, 框架
為了講述的方便,上面畫了CPU+主存的框架。這基本上是現在復雜CPU的主流做法,CPU內部包含控制器、運算器、寄存器,使用虛擬地址,經過MMU可以轉化成物理地址。其中MMU里面有一個頁表高速緩存表(Table Lookup Buffer,簡稱TLB)和頁表遍歷單元(Table Walk Unit,簡稱TWU),當TLB緩存著要訪問的虛擬地址到物理地址的轉換關系的時候,就可以直接找到的物理地址,通過該物理地址在L1 cache中查找數據。如果TLB中沒有緩存要訪問虛擬地址對應的物理地址,這時會通過TWU模塊遍歷主存中的頁面,查找相應的物理地址,找到后再通過這個物理地址訪問L1cache。如果L1 cache中存在著要訪問的物理地址對應的內容,直接返回給相應的寄存器。如果L1 cache中沒找到相應的數據,就依次從L2、L3 cache中查找,如果在所有層級的cache中都沒查找到有效的數據,就會直接訪問主存取出物理地址對應的數據分別給到寄存器和L1 cache。
其中實線部分是命中TLB及cache的數據訪問方式,虛線部分是沒有命中TLB及cache,通過TWU和頁表訪問主存獲取數據的方式。這個框架相對于馮·諾依曼體系結構多了MMU及cache,這兩個單元主要是為了解決兩個問題,一個是地址空間保護、內存使用效率低的問題,另一個是馮·諾依曼體系結構訪問指令、數據共用存儲器慢的問題。接下來,我們分別看看各個模塊的功能。
2.1 中央處理器核心
CPU CORE是一種根據指令進行各種處理的電子電路。一般由控制器、運算器、寄存器組成。后面會專門寫篇文章,詳細分析一款ARM核的微架構。接下來,我們分別看一下各模塊的功能。
1) 控制器
控制器又稱為控制單元(Control Unit,簡稱CU),是計算機的指揮中心,只有在它的控制下,整個CPU才能夠有條不紊地工作、自動執行程序。CU包括指令寄存器、指令計數器,其中指令寄存器存放當前正在執行的指令,指令計數器總是指向下一條要執行指令的地址。CU的工作流程為:從內存中取指令、翻譯指令、分析指令。然后根據指令的含義,向有關部件發送控制命令,控制相關部件執行指令所包含的操作。具體的依次指令執行過程如下:CU通過指令計數器獲取下一條將要執行指令的地址,通過該地址獲取具體的指令存放在指令寄存器,然后對該指令解碼,如果是一個add(加法指令),會通過將寄存器中的值加載到運算器,其中寄存器中的值是從cache或者主存中獲取的,經過運算器的運算產生進位、溢出等信號反饋給控制器,產生的結果也存放在寄存器中。
2) 運算器
運算器是一個負責算術運算和邏輯運算的模塊,主要包含算術邏輯單元(Arithmetic Logic Unit,簡稱ALU)和浮點運算單元(Floating Point Unit,簡稱FPU)。 ALU的主要功能:在控制信號的作用下,完成加、減、乘、除等算術運算,以及與、或、非、異或等邏輯運算以及移位、補位等運算。 通常ALU由兩個輸入端和一個輸出端(兩個值輸入,一個結果輸出)。 FPU主要負責浮點運算和高精度整數運算。 有些FPU還具有向量運算的功能,另外一些則有專門的向量處理單元。
運算器是用與、或、非邏輯門電路搭建起來的,比如,帶進位的二進制加法電路:
運算器主要的處理對象是數據,所以數據的長度以及數據的表示方法,對運算器的影響很大。大多數通用CPU是以16、32、64位數據作為運算器一次處理數據的長度。能夠一次性對一個數據的所有位,同時處理的運算器稱為并行運算器,一次只能對數據的一個位處理的運算器稱為串行運算器。我們通常所說的“CPU是幾位的”就是指ALU一次所能處理的數據的位數。
運算器與其他部分的關系:計算機運算時,運算器的操作對象和操作種類由控制器決定。運算器操作的數據從cache或內存中讀取,處理的結果再寫入內存(或者暫時存放在內部寄存器中),而且運算器對內存數據的讀寫是由控制器來進行的。
3) 寄存器
寄存器的主要功能是存儲數據、地址及指令,并且能夠高速、自動地完成數據的存儲。寄存器是有記憶功能的器件,而且采用兩種穩定狀態0或1來記錄數據信息,所以CPU中的程序和數據都要轉換為二進制才可以存儲和操作。寄存器也是由與、或、非邏輯門電路組成的,下面就展示1bit的存儲,32個bit就是32個重復的1bit電路。
其中D為寄存器中一個bit要改變成值的輸入,B為當前寄存器的一個bit。當WE(Write Enable)為0時,B保持不變,不受D的變化影響。當WE為1時,這時候D為0時,B為0,并將該值存到電路中,當D為1時,B為1,并將該值存到電路中。
2.2 MMU
內存映射單元(Memory Map Unit,簡稱MMU),指的是將虛擬地址轉化成物理地址的模塊。MMU包含了兩個模塊:頁表查找表(Table Lookup Buffer,簡稱TLB)和頁表遍歷單元(Table Walk Unit,簡稱TWU)。TLB是一個高速緩存,用于緩存頁表轉換的結果,從而減少頁表查詢的時間。一個完整的頁表翻譯和查找的過程叫做頁表查詢,頁表查詢是通過硬件模塊TWU自動完成的,但是頁表的維護需要軟件來完成,且存放在主存中,因此頁表查詢是一個耗時的過程。當TLB未命中時,MMU才會通過TWU查詢頁表,從而得到翻譯后的物理地址,這個虛擬地址及物理地址的映射也會存儲在TLB中。
對于ARM這樣的處理器,CPU看到的都是虛擬地址,需要經過MMU轉化為物理地址,才能訪問cache或者內存拿到物理地址中的內容。你可能會疑問,為什么需要虛擬內存,直接用物理內存不行嗎?是的,不行。為了做進程地址空間的隔離及提升內存的使用效率,使用虛擬內存是很有必要的。后面會專門寫一篇文章專門講述MMU。
2.3 緩存
由于CPU與內存之間存在很大的速度差(兩者相差上百倍),同時又因為程序的加載有時間及空間局部性的特點,也就是說程序的一個內存位置被訪問了,附近的位置很快也會被訪問到。那么我們可以把內存中的部分代碼提前加載到訪問更快的cache里面。既然cache的主要作用是CPU與主存的緩沖層,那么cache的速度應該接近于CPU,基本上是與CPU同頻運作。一般緩存都集成在CPU芯片上,L1 cache分為L1D和L1I cache,L1D、L1I和L2 cache在同一個cpu上,L3 cache一般是多個cpu間共享。既然cache的訪問速度這么快是不是越大越好,其實并不是,單拿成本和die的面積來說cache就不能做的太大。后面會專門寫一篇文章專門講述cache。
現代計算機或嵌入式系統的存儲設備一般有cache、內存、SSD、HDD硬盤。這些存儲設備越靠近 CPU 速度越快,容量越小,價格越貴。
寄存器(Register):寄存器與其說是存儲器,其實更像是 CPU 本身的一部分,只能存放極其有限的信息,但是速度非常快,和CPU同步。
高速緩存(CPU Cache):使用 靜態隨機存取存儲器(Static Random-Access Memory,簡稱SRAM)的芯片。
內存(DRAM):使用動態隨機存取存儲器(Dynamic Random Access Memory,簡稱DRAM)的芯片,比起 SRAM 來說,它的密度更高,有更大的容量,而且它也比 SRAM 芯片便宜不少。
硬盤:如固態硬盤(Solid-state drive 或 Solid-state disk,簡稱SSD)、硬盤(Hard Disk Drive,簡稱HDD)。
每一種存儲器設備只和它相鄰的存儲設備打交道。比如,CPU Cache是從內存里加載而來的,或者需要寫回內存,并不會直接寫回數據到硬盤,也不會直接從硬盤加載數據到CPU Cache中,而是先加載到內存,再從內存加載到cache中。
可以看出,越是速度快的設備,容量就越小。這里一共10M的cache,成本只是幾十美元。而 8GB 的內存、128G 的 SSD 以及 1T 的 HDD,大概零售價格加在一起,也就和我們的高速緩存的價格差不多。
2.4 主存
主存里分別存儲了各種數據,包括代碼段、數據段、字符串、地址等。它的讀寫速度相對寄存器、cache慢了很多,但是單位成本卻低了很多。通過系統中的存儲金字塔設計,利用程序的時間及空間局部性原理,可以很好地利用主存的價格優勢,彌補讀寫時間慢的問題。后面會專門寫一篇文章講解主存。
2.5 總線
雖然從上面的框圖上不能直觀地看到BUS總線的存在,但是地址、數據的傳輸都是依賴總線完成的。它就像一條高速公路,快速完成各個單元間的數據交換,也是數據從內存流進和流出CPU的地方。CPU總線(前端總線)傳輸速率決定著CPU與內存之間傳輸數據的速度快慢。CPU總線速率越高,CPU等待從內存取指令和數據時間越少,運行程序速度越快??偩€又細分成數據總線、地址總線和控制總線。后面會專門寫一篇文章講解總線相關的知識。
3,CPU的運行過程
3.1 指令集
指令集架構(Instruction Set Architecture,簡稱ISA)是CPU和軟件之間的橋梁。ISA包含指令集、特群集、寄存器、執行模式、安全擴展、性能加速擴展等方面。其中,指令集是ISA的重要組成部分,通常包含一系列不同功能的指令,用于數據搬移、計算、內存訪問、過程調用等。CPU在運行操作系統或者應用程序的時候,實際上是在執行它被編譯后所包含的指令。根據執行指令的特征,CPU分為精簡指令集計算機(Reduced Instruction Set Conputer,簡稱RISC)和復雜指令集計算機(Complex Instruction Set Conputer,簡稱CISC)。
RISC類CPU的指令功能單純,種類少。相對地,CISC類CPU指令功能復雜,種類繁多。RISC指令精簡的好處是CPU內部構造可以簡化,適合高速操作,但是在進行相同的操作時,由于每條指令功能單純,所以與CISC相比,RISC需要使用更多的指令數量。雖然CISC的內部構造復雜不適合高速操作,但進行相同處理時指令數比RISC要少。
RISC架構最大的特點是只使用載入和存儲指令訪問內存,之中架構成為載入存儲架構。這樣做的好處是可以簡化指令集和流水線的設計,在這種架構下,運算指令只能對寄存器中的數據進行操作。RISC和CISC兩種架構各有所長,在追求高速運行的CPU領域中,RISC被認為更具優勢。雖然這些年,Intel和AMD兩家公司的CPU指令集依然是CISC的,但內部卻將復雜指令分解成簡單指令,使得內部像RISC一樣工作。
3.2 CPU一般運行過程
CPU從cache或主存中取出指令,然后放入指令寄存器,控制器對該指令進行譯碼。最終把指令分解成一系列的微操作,然后發出各種控制命令,執行微操作序列,從而完成一條指令的執行。指令是CPU規定執行操作的類型和操作數的基本命令。指令是由一個字節或者多個字節組成(對于arm64,指令長度是4個字節),其中包括操作碼字段、一個或多個有關操作數地址的字段以及一些表征機器狀態的狀態字以及特征碼。有的指令中也直接包含操作數本身,且用二進制序列表示。指令的構造如下:
1) 取指
取指令(Instruction Fetch,簡稱IF)階段是將一條指令從cache或主存中獲取指令到指令寄存器的過程。CPU中有一個程序計數器(Program Counter,簡稱PC)寄存器,其中保存著將要執行指令的地址。指令讀取是通過將PC寄存器的值輸出給cache或者內存,然后由cache或內存返回該值對應地址中的指令。當一條指令被取出后,PC中的數值將根據指令字長度自動遞增。
2) 譯碼
取出指令后,CPU會立即進入指令譯碼(Instruction Decode,簡稱ID)階段。在指令譯碼階段,指令譯碼器按照預定的指令格式,對取回的指令進行拆分和解釋,識別區分出不同的指令類別以及各種獲取操作數的方法。指令有很多種,有進行各種運算的指令、控制下一條命令的指令、對內存進行讀寫的命令,還有對CPU進行控制的指令。
3) 執行
在取指令和指令譯碼階段之后,接著進入執行指令(Execute,簡稱EX)階段。此階段的任務是完成指令所規定的各種操作,實現具體指令的功能。為此,CPU的不同部分的組件被連接起來,以執行所需的操作。例如,執行一個加法運算,ALU將會連接到一組輸入和一組輸出。輸入提供了要進行相加運算的數值,而輸出求和后的結果。如果加法運算產生一個對該CPU處理而言過大的結果,在標志暫存器里,運算溢出(Arithmetic Overflow,簡稱AO)標志可能會被設置。
4) 訪存
根據指令需要,有可能要訪問主存,讀取操作數,這樣就進入了訪存取數的階段。此階段的任務是:根據指令中的地址碼,經過MMU將虛擬地址轉化成物理地址,根據物理地址得到操作數在cache或主存中的地址,并從cache或主存中讀取該操作數用于運算。
5) 寫回
結果寫回(Write Back,簡稱WB)階段一般把執行指令階段的運行結果數據寫回到內部寄存器中,以便被后續的指令快速地存取。在有些情況下,結果數據也可被寫入相對較慢、但較廉價且容量較大的主存。許多指令還會改變程序狀態寄存器中標志位的狀態,這些標志位標識著不同的操作結果,可被用來影響程序的動作。在指令執行完畢、結果數據寫回之后,若無意外事件(如結果溢出等)發生,CPU就接著從程序計數器PC中取得下一條指令地址,開始新一輪的循環,下一個指令周期將順序取出下一條指令。
3.3 CPU中斷流程
在正常情況下,CPU 可以順序執行,也可以分支執行,這些總歸是按照既定順序去執行?,F實中,有時需要暫時中斷CPU的當前執行流,讓CPU去做點其他的工作,再回頭來繼續原來的執行流。因此CPU硬件提供了一種中斷機制,可以先讓CPU停下,等中斷服務程序執行完后,再切回來:
保存PC:保存當前的 PC 的值到內存的某個位置
修改PC:修改 PC 的值,讓執行其他執行流
回原PC:其他執行流執行結束之后,通過將剛才保存的 PC 值恢復到 PC 寄存器
繼續原執行流:繼續中斷前的執行流
審核編輯:湯梓紅
評論
查看更多