手把手教你設計CPU(蜂鳥書)讀書筆記

寫在最前

這本書講的是如何用verilog,以riscv爲指令集,設計一款CPU。也就是書中說的蜂鳥E200。之前沒有看過類似的書,對CPU的工作流程也不熟悉。這本書以verilog爲載體,介紹了CPU的基本原理,對於第一次接觸CPU內部眼裏的菜鳥來說,簡直不要太神奇。而且本書開源代碼,只要有一塊fpga,你也能夠自己做出一塊CPU來。

第一章~第四章

這是本書的第一部分,主要是一些介紹。諸如RISCV之前的一些架構,以及RV指令集的特性。第三章介紹不同的RV版本,第四章介紹本書的E200的特性。

第五章 E200設計總覽

講了一些很有用的基礎知識

  1. 架構指的是指令集架構,微架構是根據架構設計的硬件佈局
  2. 處理器或者CPU往往是一個完整的SOC,和處理器核或者core是處理器的運算核心。

E200的設計哲學

  1. 模塊化和可重用性
  2. 面積最小化
  3. 結構簡單化
  4. 性能不追求極端,夠用即可

E200的代碼風格

  1. 使用標準DFF模塊例化生成寄存器
  2. 使用assign語句代替ifelse和case
    • 不能傳播不定態
    • 面積大
  3. 代碼即註釋
  4. 禁止使用CLOCK和RESET

第六章 流水線

五級流水線:取指,譯碼,執行,訪存,寫回

流水線也不是必須的,有的處理器用的是狀態機。並且流水線的深度不同的處理器也有不同的設置。

流水線的衝突

  1. 數據衝突

    • WAR,先讀後寫
    • WAW,先寫後寫
    • RAW,先寫後讀

    這是三種數據依賴性,其中WAW,WAR可以通過寄存器重命名的方式去除依賴,而RAW是真數據相關,就是它必須要讀已經寫了的這個數據。如果發生這種情況,就要等待寫完纔可以。有一些解決方法, 比如找個東西記錄這種相關性。

E200的流水線

在這裏插入圖片描述

  1. IFU取指
  2. EXU用來譯碼和執行
  3. LSU用來訪存
  4. WB用來寫回

第七章 取指

概述

  1. 對於非分支跳轉指令,就連續不斷地進行取指即可,就算是不是對齊的32位指令,最好也能夠每個週期都能夠讀一條指令
  2. 對於分支跳轉指令,能夠快速判斷是否需要跳轉。如果需要跳轉,就從新的PC取出指令。
  3. 從ITCM或者ICACHE中取指令,E200用的是ITCM,很快。
  4. 非對齊的指令,對於順序執行的,只需要緩存下來,等下次取指拼接到一起就可以了,不耽誤時間。但是對於跳轉的那種,就用多bank,並行一次取倆,也可以在一個週期內完成。

分支

  1. 無條件直接跳轉,比如jal x5,offset。這種,立即數就能跳
  2. 無條件簡潔跳轉,不是立即數了,需要從寄存器讀跳轉的地址
  3. 帶條件直接跳
  4. 帶條件間接跳,這個RV裏沒有

爲了提升性能,就要進行分支預測。首先要預測方向,也就是到底跳不跳,還有就是預測地址。

預測方向就有各種方法,比如靜態預測和動態預測。

預測地址是除了直接跳轉,間接跳轉是需要讀寄存器的,很耗費時間。就用比如保存之前的分支語句,如果匹配,就直接跳到那個地址之類的方法。

RV對於取指的簡化

  1. 規整的編碼指令格式
  2. 指令長度指示碼放於低位
  3. 簡單的分支跳轉指令
  4. 沒有分支延遲槽指令。分支延遲槽是在分支後面放一些不受分支影響的指令,默認現在的分支預測精度已經很高,爲了減少硬件成本。
  5. 提供明確的靜態分支預測依據
  6. 提供明確的RAS依據,這個是預測跳轉地址的一個方法

IFU的實現

在這裏插入圖片描述

  1. 首先從ITCM取指,然後放到IR和PC裏,IR是指令寄存器。同時用minidecode進行初步地譯碼來判斷當前指令是普通指令還是分支跳轉,然後生成用BPU來做分支預測,生成下一個PC
  2. 如果取指令的地址不在ITCM裏,就會通過BIU訪問外部存儲。

第八章 執行

在這裏插入圖片描述

  1. 根據IR中的指令,譯碼和派遣
  2. 讀寄存器,RD-Regfile
  3. 維護數據的相關性,OITF
  4. 給各種運算單元執行,ALU,長指令,LSU,EAI等
  5. 交付指令
  6. 寫回寄存器,WB-Regfile
  • 系統中有一些特殊的寄存器,叫CSR寄存器,爲了存儲系統的一些狀態。
  • 實際的派遣是ALU進行的

流水線衝突,長指令和OITF

  1. 資源衝突:就是運算單元的衝突,就等待
  2. 數據衝突:正在派遣的指令和尚未執行完成的長指令存在RAW和WAW依賴。

爲了檢測出這種數據依賴,E200實現了一個OITF模塊。其中存儲的是已經派遣但是還未寫回的長指令信息。然後每次在進行指令派遣的時候,就把本指令的操作數和長指令的向比較,如果有相同的,就說明有相關性,就等待。

ALU+浮點單元

做各種計算

第九章 交付

我理解的交付就是這條指令能夠執行,而不是執行完成。

首先ALU會計算是否需要跳轉,計算出來之後就發給交付模塊。如果交付模塊發現結果和預測結果一樣,就不會沖刷流水線,否則就沖刷流水線。

第十章 寫回

兩個仲裁

  1. 最終寫回仲裁:長指令比單指令有更高優先級。如果沒有長指令寫回,單指令可以比更早位置的長指令寫回。
  2. 長指令寫回仲裁:根據OITF判斷長指令的先後關係,嚴格控制長指令的寫回順序

第十一章 存儲器架構

在這裏插入圖片描述

AGU address generation unit

是ALU的一部分,用於產生訪存地址。

LSU ITCM DTCM

A字擴展指令

這裏是用於多核操作的原子指令,包括互斥操作等的實現。

第十二章 BIU Bus Interface Unit

E200提出了自己的總線協議ICB

實現了一從多主和多主一從以及多主多從的總線連接方式。

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-spFHBnCB-1591688314612)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20200609151117973.png)]

第十三章 中斷和異常

廣義上的異常包含了狹義的中斷和異常。異常主要包括

  1. 同步異常:由於執行程序指令或者試圖執行程序指令而造成的異常。這個原因能夠被精確定位到某一個指令,而且無論運行多少次,都能夠被精確地復現
  2. 異步異常:最常見的異步異常就是外部中斷,稱之爲精確異步異常。還有非精確異步異常。

異常處理機制

  1. 停止執行當前指令,轉而從CSR寄存器mtvec定義的PC地址開始執行
  2. 更新其他幾個寄存器:異常原因,異常PC,異常值,狀態
  3. 退出異常
    • 從mepc定義的pc開始執行
    • 更新CSR寄存器mstatus

RV架構中斷定義

  1. 外部中斷:來自處理器核外部的中斷,還有一箇中斷控制器PLIC,用來仲裁外部中斷
  2. 計時器中斷:mtime,mtimecmp
  3. 軟件中斷:軟件自己往msip寄存器裏寫1觸發中斷
  4. 調試中斷

一般外部中斷優先級最高,軟件中斷次之,計時器中斷再次。

在這裏插入圖片描述

其他章

第十四章是講如何調試,十五章講低功耗的各方面優化,十六章講RV能夠進行協處理器擴展。第三部分主要講如何在實際平臺上實現E200。附錄講了RV的指令集等其他RV基礎知識。在此不多贅述。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章