存儲器架構
存儲器架構簡介
雖然這部分的内容是存儲器,但是因為蜂鳥的原書将BIU總線放到了存儲器架構部分的後面,考慮到兩者關系還是比較密切的,這裡就把存儲器架構和總線協定放在一起,個人認為這樣更便于了解
蜂鳥E203的處理器中沒有配備緩存,處理器外則分别配備了ITCM和DTCM用于存儲指令和資料
雖然在常見的PC的CPU大都配備了緩存,甚至有一二三級不同緩存用來提高核心執行效率,但實際上大部分的低功耗中低性能處理器并沒有配備緩存,主要原因在于以下幾點:
-
緩存無法保證明時性
緩存利用軟體程式的時間局部性和空間局部性,将存儲器資料動态映射到容量很小的緩存中,這樣減小了通路存儲器的平均延遲。但是正因如此,通路緩存存在着巨大的不确定性,最直覺的,一旦緩存不命中就會導緻取指或訪存時間增加,這就導緻實時性不好
針對這一點,大多低功耗中低性能處理器都使用延遲确定的ITCM和DTCM
-
嵌入式裝置軟體規模較小
在嵌入式領域的軟體代碼一般很小,所需的資料段也很小,是以使用片上SRAM、片内FLASH或者ITCM/DTCM便可以滿足其需求,是以緩存的優點就被大大影響,不能說一點用都沒有,隻能說映射了個寂寞
-
緩存面積功耗大
緩存會消耗大量的晶片面積和功耗,從AMD的5900x就可以看出來,32MB的三級緩存面積都快比核心本體大了
在低功耗的中低性能處理器中不可能費盡心思引入一個徒增功耗還沒什麼用的東西
正因如此,即使是ARM的高端Cortex-M7核心也隻是配備了一個16KB的I-Cache(指令緩存)和一個16KB的D-Cache(資料緩存),整體的緩存隻有一級——補充一下,這玩意是六級流水線、雙發射、亂序執行的大号處理器,全力開跑甚至需要散熱片
蜂鳥E203采用的是哈佛架構,主要特點如下:
- 程式和資料單獨存儲
- 每個存儲器獨立編址、獨立通路
- 使用資料總線和指令總線獨立連接配接兩個存儲器到核心
- 取址和執行并行處理
搞嵌入式的不可能沒見過哈佛架構,想必各位已經品鑒的足夠多了。然而現在的哈佛架構正在逐漸和馮諾依曼架構合體,具體表現如下:
- 系統往往隻有一套位址空間,程式的指令存儲位址和資料存儲位址指向同一套位址空間的不同實體位址,在使用進階語言編寫程式時對馮氏架構和佛氏架構一視同仁,編譯器和燒錄器會自動搞定底層的東西
- 現代處理器往往會配備一級指令緩存和資料緩存,搞得馮氏架構和佛氏架構一樣
- 現代的高端處理器往往會配備二級緩存、三級緩存,在這兩個緩存中資料、指令是混合存儲的
是以說現代處理器中,低功耗處理器正在通過上層封裝向馮氏架構靠攏;而高性能處理器則正在通過硬體設計向佛氏架構靠攏
蜂鳥E203的存儲器架構
RISC-V架構對于存儲器也進行了一定簡化
-
僅支援小端格式
小端格式是現在CPU的主流應用,RISC-V架構也就僅支援小端格式,這就簡化了硬體設計
-
沒有位址自增自減
RISC-V取消了存儲器讀寫指令的位址自增自減模式,可以簡化位址的生成邏輯
-
沒有一次讀/寫多個資料的指令
RISC-V沒有定義能夠從存儲器中一次讀/寫多個資料的指令,雖然減少了單條指令的訪存效率,但是大大簡化了硬體的實作
-
專用存儲器讀寫指令
使用Load進行存儲器讀
使用Store進行存儲器寫
RISC-V還定義了7條存儲器讀指令和存儲器寫指令用來進行位元組、半字、單字的讀寫操作
-
松散存儲器模型
RISC-V使用松散存儲器模型,對不同位址訪存的順序不做要求,使用Fence和Fence.I指令來強行界定訪存的順序
-
擴充指令
RISC-V定義了一種擴充指令子集,用于支援多線程狀态下通路存儲器的原子操作或同步操作
包括Atomic Memory Operation(AMO)指令、Load-Reserved指令、Store-Conditional指令
蜂鳥E203的實作則基于RISC-V的規定設計了四個子產品:
-
位址生成單元AGU
為讀寫指令和“A”擴充指令生成存儲器通路位址
-
LSU
存儲器通路的控制子產品
-
指令緊耦合存儲器ITCM
作為存儲器子系統的指令存儲部件,但是也能用于存儲資料而被讀寫指令通路
-
資料緊耦合存儲器DTCM
作為存儲器子系統的資料存儲部件
以上DTCM和ITCM并聯到LSU的位址判斷和資料對齊控制器之間,AGU則旁挂在LSU上,LSU通過BIU與ICB總線相連
AGU(Address Generation Unit)
因為AGU需要将第一個寄存器索引的源操作數和符号位擴充的立即數相加來得到讀寫指令最終的方寸位址,是以需要用到加法器
是以蜂鳥E203中将AGU和ALU放在一起,共用ALU的加法器來節省面積
其代碼儲存在/rtl/e203/core/e203_exu_alu.v、e203_exu_dpath.v、e203_exu_lsuagu.v檔案中,很明顯和ALU放在了一起
其中e203_exu_alu.v檔案中實作了AGU所用的加法器和多路選擇器的硬體結構
e203_exu_dpath.v檔案則實作了AGU的資料處理代碼,其中主子產品就是ALU的共享資料通路,複用了ALU處例化的加法器
RISC-V架構對于位址非對齊的讀寫指令可以使用硬體支援也可以使用軟體通過異常服務程式的方式采用軟體支援,而蜂鳥E203采用軟體支援的解決方案,ALU對生成出的訪存位址進行判斷,如果位址非對齊,則産生異常标志,通過ALU傳送給傳遞子產品,傳遞子產品則據此産生異常,相關代碼在e203_exu_lsuagu.v檔案中
此外,e203_exu_lsuagu.v檔案中還實作了AGU的控制和選擇代碼,但是不包括加法器部分;生成位址部分的HDL代碼也在這個檔案中。檔案最後還例化了ICB接口用于挂載到BIU
詳細内容可以參考源代碼,這裡不再贅述
LSU(Load Store Unit)
這是蜂鳥E203處理器核存儲器子系統的主要控制單元,源代碼儲存在/rtl/e203/core/e203_lsu.v和e203_lsu_ctrl.v中,它們的架構和代碼實作與BIU子產品很相似,具體情況可以參考下面的總線協定部分
LSU有2組輸入ICB總線接口,分别接入AGU和EAI協處理器的接口;3組輸出ICB接口,分别分發給BIU、DTCM和ITCM;LSU還配備了一個寫回接口。2組輸入總線通過一個ICB彙合子產品合成一組ICB總線,采用優先級仲裁的邏輯,EAI總線具有更高的優先級,經過彙合之後的ICB總線通過指令通道的位址進行判斷,通過其通路的位址區間産生分發資訊,随後接入的ICB分發子產品會将其分發給不同存儲器元件的ICB接口
如果EAI需要通路存儲器,就需要在LSU這裡進行配置
特别地,LSU使用的ICB彙合和ICB分發子產品的FIFO深度均為1,也就是LSU預設隻支援1個滞外傳輸
最終的傳回資料需要經過尺寸對齊後經過LSU寫回接口寫回。對于可能出現的存儲器通路錯誤,LSU預留了一條回報通道信号線用于傳回标志信号,異常标志會通過LSU的寫回接口傳送給核心的傳遞子產品,傳遞子產品會據此産生異常
ITCM和DTCM
蜂鳥E200系列處理器使用專用總線分别通路ITCM和DTCM,ITCM位寬為64位,DTCM位寬為32位
ITCM也有一組輸入ICB總線接口來自LSU的通路,是以ITCM所在的位址區間同樣能夠通過LSU被讀寫指令通路到用于存儲資料;另外有一組64位寬ICB總線接入到IFU,有一組32位寬的外部直接通路接口用于SoC中的外設能夠直接通路ITCM。三組輸入的ICB總線會經過一個ICB彙合子產品彙成一組ICB總線,子產品依舊采用優先級仲裁,IFU總線優先級>LSU優先級>外部直接通路接口。操作的來源資訊會被寄存,SRAM傳回的資料會根據寄存結果分發回三個總線之一
對于硬體實作,ITCM采用一塊資料寬度為64位的單口SRAM組成,可以通過config.v中的宏定義配置ITCM大小和基位址
DTCM則擁有2組輸入ICB總線接口,分别來自LSU和外部直接通路接口,具體實作和ITCM大同小異
ITCM的實作代碼為e203_itcm_ctrl.v,DTCM的實作代碼為e203_dtcm_ctrl.v
特别地,可以根據片上資源情況選擇使用ITCM和DTCM,控制例化的代碼位于e203_itcm_ram.v和e203_dtcm_ram.v,如下所示
`ifdef E203_HAS_DTCM //{
module e203_dtcm_ram(
input sd,
input ds,
input ls,
input cs,
input we,
input [`E203_DTCM_RAM_AW-1:0] addr,
input [`E203_DTCM_RAM_MW-1:0] wem,
input [`E203_DTCM_RAM_DW-1:0] din,
output [`E203_DTCM_RAM_DW-1:0] dout,
input rst_n,
input clk
);
sirv_gnrl_ram #(
.FORCE_X2ZERO(1),//Always force X to zeros
.DP(`E203_DTCM_RAM_DP),
.DW(`E203_DTCM_RAM_DW),
.MW(`E203_DTCM_RAM_MW),
.AW(`E203_DTCM_RAM_AW)
) u_e203_dtcm_gnrl_ram(
.sd (sd ),
.ds (ds ),
.ls (ls ),
.rst_n (rst_n ),
.clk (clk ),
.cs (cs ),
.we (we ),
.addr(addr),
.din (din ),
.wem (wem ),
.dout(dout)
);
endmodule
`endif//}
`ifdef E203_HAS_ITCM //{
module e203_itcm_ram(
input sd,
input ds,
input ls,
input cs,
input we,
input [`E203_ITCM_RAM_AW-1:0] addr,
input [`E203_ITCM_RAM_MW-1:0] wem,
input [`E203_ITCM_RAM_DW-1:0] din,
output [`E203_ITCM_RAM_DW-1:0] dout,
input rst_n,
input clk
);
sirv_gnrl_ram #(
`ifndef E203_HAS_ECC//{
.FORCE_X2ZERO(0),
`endif//}
.DP(`E203_ITCM_RAM_DP),
.DW(`E203_ITCM_RAM_DW),
.MW(`E203_ITCM_RAM_MW),
.AW(`E203_ITCM_RAM_AW)
) u_e203_itcm_gnrl_ram(
.sd (sd ),
.ds (ds ),
.ls (ls ),
.rst_n (rst_n ),
.clk (clk ),
.cs (cs ),
.we (we ),
.addr(addr),
.din (din ),
.wem (wem ),
.dout(dout)
);
endmodule
`endif//}
其他指令處理
蜂鳥203預設支援“A”擴充指令子集
詳細内容可以檢視LSU部分代碼
蜂鳥E203通過在派遣控制子產品、傳遞子產品、分支處理子產品等部分加入Fence指令處理的代碼實作了對Fence和Fence.I指令的處理
這些内容大都在源碼部分用注釋寫明,不再贅述
蜂鳥E200系列部分核心配備了ECC算法來對SRAM進行保護,但蜂鳥E203并沒有配備
總線協定
蜂鳥E203并沒有使用AMBA協定中規定的任何一種總線
這就導緻它的總線部署和修改相當惡心
但是好在這玩意的時序和AHB總線比較相似,雖然不能在vivado中一鍵生成,但是封裝一個IP并不是要人命的問題
雖然原書和相關教程中總結比較了各個總線的優缺點,但個人認為采用自定義的總線協定對于一個以應用為目的的處理器而言實屬逆天。最重要的是這個破總線給筆者的比賽和隊員們的心理造成了極大損傷!
不管怎麼吐槽,以學習為目的看待這個自定義總線協定還是可取的(況且這玩意好歹能算是國産總線協定,戰狼狂喜)
ICB總線協定
該總線協定和AHB和AXI協定比較類似,最主要的特性如下(括号内注明和哪個協定類似):
- 具有兩個獨立的通道,讀寫操作共用位址通道,傳回結果共用傳回通道
- 位址和資料傳輸階段分離(AXI)
- 位址區間尋址,支援任意主從數目和拓撲結構,支援多個滞外傳輸(AXI)
- 使用位元組掩碼控制寫操作(AXI)
- 支援非對齊位址的資料通路(AXI)
- 每個讀寫操作都會在位址通道上産生位址(AHB)
- 不支援亂序傳回亂序完成,必須順序回報結果(AHB)
- 實作簡單,易于橋接到其他總線(其實沒什麼用,因為橋接花的時間大于學習并實作這個總線接口的時間),易于添加流水線獲得更高頻率的時序(俗稱體質好,能超頻,但如果用蜂鳥E203在FPGA上實作的話并沒有什麼用)
總線時序不能說和AXI時序一模一樣,隻能說差不多得了,是以在這裡不多介紹,想了解詳細資訊可以檢視官方書籍和官網的時序圖
BIU
位于rtl/e203/core/e203_biu.v
BIU主要負責接收來自IFU和LSU的存儲器通路請求,使用标準的ICB接口向核心、外設分發,通過判斷指令通路的位址區間來通路以下五種外設接口:快速IO接口、私有外設幾口、系統存儲接口、CLIENT接口、PLIC接口
BIU有2組輸入接口,分别來自IFU和LSU單元,通過一個ICB彙合子產品合成一組ICB總線,采用優先級仲裁,LSU具有更高的優先級
為了截斷外界和處理器核心之間的時序路徑,在彙合的ICB總線處額外插入了一組乒乓緩存
ICB彙合、分發兩個子產品的FIFO深度預設配置為1,它預設隻支援一個滞外交易,用于減少面積開銷
此外,如果IFU通路到裝置區間,會直接通過回報通道傳回錯誤标志
特别地,LSU和BIU的結構很相似,除了接口方向、數目不同外,本質上都是用于轉發總線資料的“交換機”
詳細内容參考代碼即可
片上SoC總線
E200系列處理器配套SoC中,總線分為兩組:附屬于BIU的系統存儲總線和通過BIU與核心耦合的私有外設總線
系統存儲總線用于通路SoC中的ROM、OTP、FLASH隻讀區間等外設存儲器
私有外設總線則用于外設寄存器映射和通路
其中所有存在時序相容的重要路徑都會插入乒乓緩存來砍斷前後的時序路徑;任何需要跨越異步時鐘域或整數倍分頻時鐘域都會插入異步FIFO或流水線級數