# Build a CPU ###### tags: `IT鐵人` ## 抽象化設計 建構一台電腦時,他要能執行所有指定ISA的指令,以MIPS來說,就要執行MIPS裡面的所有指令,我們用底下的指令來建構電腦: | Memory存取 | 算術邏輯運算 | 流程控制(不照順序執行指令) | |-|-|-| | lw, sw | add, sub, and, or, slt(向左shift,等同乘以2) | beq(相等時跳到其他指令), j(直接跳到其他指令) | 在建構之前,我們要先介紹一些基本零件 <style> table th:first-of-type { width: 50%; } table th:nth-of-type(2) { width: 50%; } </style> |基本零件|說明 | |-|-| ![](https://i.imgur.com/WCjlllR.png )| Register file(暫存器的集合):透過Register編號,我們可以讀取或寫入任何一個Register,MIPS 2000有32個32位元一般目的Register,因此需要5bits來指定Register,Register file可以同時讀取2個即寫入1個Register內容,另外還需要1bit的寫入控制訊號來指定是否要寫入Register。 | | ![](https://i.imgur.com/syc1ynI.png) | ALU:執行運算的零件,一次只允許2個32bits的運算元參與運算,並由4bits的ALU控制訊號決定運算的類別(add, sub, or...),另外,ALU有一個1bit的zero indicator表示運算結果是否為0。 | | ![](https://i.imgur.com/X1Mg5hM.png) | Data Memory:提供資料儲存的零件,提供位址輸入口、資料輸入口、資料輸出口,另外還需要指定要寫入還是讀取的各1bit輸入口。 | | ![](https://i.imgur.com/fKguZwZ.png) | Instruction Memory:儲存程式的零件,有一個32bits的指令輸出口跟一個32bits的指令輸入口, | | ![](https://i.imgur.com/Y7mA1Lr.png) | Adder:固定執行32bits加法並產上32bits結果的零件,雖然功能ALU也能做到,只是因為另外用一個零件執行比較省時間。它的用處在於(1)增加PC(program counter)的值到下一個指令,(2)計算branch指令的目的指令(target address)。| | ![](https://i.imgur.com/ZE1lKLj.png) | Sign Extension Unit:用來將16bits有號數擴充成32bits有號數的零件,轉成32bits是為了能夠丟進ALU進行加法。 | | ![](https://i.imgur.com/9uXhN7X.png) | Program Counter(PC):32bits特殊目的Register,永遠存放下一個要被執行的指令所在的記憶體位址。 | ## 單一時脈電腦資料路徑的結構 現在我們知道了基本零件有哪些,接下來要做的事情,就是把一個一個執行程式的步驟組起來,最後再把每個步驟串在一起,會稍微有點難,不過一起努力ㄅ~ ![](https://i.imgur.com/Nz8h77l.png) ### Instruction fetch 第一步我們要將執行程式的位址拿出來,所以需要PC紀錄執行到哪裡、Adder將指令位置往後推、Instruction Memory取得指令的內容。 組合的結果如下圖: ![](https://i.imgur.com/UWBK7kY.png) > 每次將PC加4(因為一個指令32bits = 4bytes,所以指令位置4個4個一組)。 > PC接入Instruction Memory。 > Adder的結果送回PC。 ### R-type指令資料路徑 R-type讀取兩個Register的值,進行運算後存回去一個Register,所以我們需要Register file存取數值、ALU計算數值。 組合結果如下圖: ![](https://i.imgur.com/TNmodQ2.png) >取得Instrucion後,將三個Register號碼輸入。 >可以得到兩個數值,丟進去ALU計算。 >將結果丟回Register file中。 ### 載入指令資料路徑(load word) 載入指令是將指定的Memory Address資料複製到指定的Register中,而且Address是將Register的資料加上某個常數,另外要把16bits的常數extend成32bits才能進去ALU進行運算。 所以我們需要Register file得到資料、ALU計算記憶體位址、Data Memory獲取記憶體資料,另外需要Sign extend擴充成32bits。 組合結果如下圖: ![](https://i.imgur.com/EfWJnbB.png) > 得到指令後,將Register資料讀出來(target Register、base memory address),常數丟入Sign extension Unit。 > 運算結果丟入Data Memory得到數值。 > 將數值丟回Register。 ### 儲存指令資料路徑(store word) 跟載入指令相似,只不過是將Register的內容丟進Data Memory中,所以我們需要的東西跟載入指令相同。 組合結果跟載入指令一樣: ![](https://i.imgur.com/EfWJnbB.png) > 不同的點在於Memory的資料不用回到Register file中。 > 並且Read data 2的資料要送進Memory ### 相等分支指令資料途徑(branch on equal) 如果兩個Register的資料相同,就要跳到指定的位置執行指令,所以要將常數extend之後丟到Adder中,改變PC的數值,需要的零件會有Register file、ALU比較是否相等、Sign Extension Unit擴充位元、Adder計算PC位址。 組合結果如下圖: ![](https://i.imgur.com/BzBmlxk.png) > 比較結果後傳送到branch control logic,由他決定是否要選擇常數加入PC ### Combine 比較麻煩的是加入Control之後需要的說明很多,不過基本上就是那些決定Read, Write, ALUop或是決定要用哪個來當作輸入時,都需要經過一個選擇器或是由Control Unit決定,經過層層組合後,整個CPU的樣子就會像這樣: ![](https://i.imgur.com/vPQ4t7Z.png) 藍色的線代表Control的部分,其他黑色的深淺不重要,只是圖片在敘述不同的重點而已。 稍微有點難理解,我們可以將每個步驟要做的事情放進去圖上看,就會發現它滿足了每一個需求了,能夠自己畫出這張圖的話,相信對這個章節已經理解不少了。 ## 下回預告 在這邊我們把CPU的datapath畫出來了,只是為了增加它的效能,我們會需要在中間設立像是儲存點的東西,才能讓一個一個指令接連進入,也就是Pipeline。 如果覺得這回已經夠地獄的話,下回會再恐怖一些,嘎油餒~ | 上一篇 | 下一篇 | |-|-| |[誰是最棒的狗勾](https://hackmd.io/@dZfCcN4hT8aUuDPv3B8CWQ/Bk4NoT7kt) | [Pipeline](https://hackmd.io/@dZfCcN4hT8aUuDPv3B8CWQ/rynNyOKJY) |