Rocket-chip-RoCC(2)
rocket-chip-rocc
關於rocc的內容很多,我會分多章進行講解。
初步規劃以下面章節為劃分。
1. 協議,自定義指令說明。
2. rocket-chip RoCC各模組的scala程式碼說明。
3. 軟體程式碼編譯實現。
4. rocket-chip RoCC各模組硬體實現和硬體模擬。
第二部分rocket-chip RoCC各模組的scala程式碼說明。
1) Rocket-chip中的定製CSR暫存器
利用grep指令搜尋scala中關於0x7c0和0x7c1的內容,結果如下圖。
順著找下去可以找到RocketCore.scala模組。
利用bpmCSR(bpmCSRId=0x7c0)和chickenCSR(chickenCSRId=0x7c1)定義不同的方法。
getOrElse()主要就是防範措施,如果有值,那就可以得到這個值,如果沒有就會得到一個預設值。
def getOrElse[B1 >: B](key: A, default: => B1): B1 = get(key) match {
case Some(v) => v
case None => default
}
從API中可以看出,傳入的引數是(key,default)這種形式,返回值是:如果有key那就get(key),如果沒有,就返回default。
在程式碼中的意思是如果chickenCSRId=0x7c1存在相應的bit,則取對應bit的值,如果不存在相應的bit,則取false.B/true.B值,固定相應def的值。
可以通過繼續追查disableICachePrefetch等關鍵字,找到使用這些def的具體位置。
0x7c0和0x7c1的內相關容可以看前文。
2) Rocket-chip中定製指令的使用
我們利用grep和正規表示式可以輕易搜到定製指令相關的scala原始檔,如下圖所示。
可以看到,與rocket-chip定製指令相關的scala檔案有sybsystem/Configs.scala和tile/LazyRoCC.scala。
在sybsystem/Configs.scala中對各定製指令模組進行例化,並指定各模組使用的定製指令編號,具體入下圖。
再利用WithRoccExample作為關鍵字進行搜尋後,可以在system/Configs.scala檔案中找到WithRoccExample的呼叫,使用的方式為:new WithRoccExample ++。這樣編譯後,生成的rocket-chip RTL就會帶有accumulator、translator、counter和blackbox這四個模組。
下面對tile/LazyRoCC.scala的部分程式碼進行簡單說明。
先看一下rocc統一的模組埠,如下圖。
我在第一章節已經說明了,custom0~3都是使用R類指令格式的,所以可以看到上圖中RoCCInstruction就是按照R類指令格式來定義的,funct就是funct7,而xd、xs1和xs2就是funct3。在accumulator模組中xs1和xs2沒有用到,xd是作為需要返回計算結果到rd暫存器的標誌。也就是說,funct、rs2(32個通用暫存器的編號)、rs1(32個通用暫存器的編號)、xd、xs1、xs2、rd(32個通用暫存器的編號)、opcode都要以散開訊號的形式進入到rocc模組中,這裡的rocc模組沒有特定指明是哪個,也就是全部都要遵守這個約定。
繼續看RoCCCommand,首先將剛定義的RoCCInstruction拿出來,然後再加了rs1、rs2和status。這裡的rs1和rs2和前面RoCCInstruction的不同,這裡的rs1和rs2不是32個通用暫存器的編號,是該對應編號通用暫存器所儲存的數值,具體就是0-31共32個通用暫存器,現在的編號2暫存器存的32bits資料為0x12345678,而編號7存的是0xFFFFAAAA,如果RoCCInstruction中的rs1為2,rs2為7,則RoCCCommand中的rs1為0x12345678,rs2為0xFFFFAAAA,它們都是xLen的寬度,我的匯流排寬度為32bits,所以它們的儲存值也就是32bits。status就是CSR暫存器mstatus的值。到這裡,RoCCCommand在RoCCInstruction的基礎上增加了三個訊號,這些在rocc模組中都要宣告這些埠。
接下來是定義RoCCResponse,是rocc模組應答的訊號,rd是通用暫存器的編號,共5bits,data是返回的計算結果,共xLen位。
然後就是RoCCCoreIO,將RoCCCommand以cmd為字首,然後散開為各個訊號,RoCCRespons則以resp為字首,然後多宣告mem、busy、initerrupt、exception這幾個訊號,很好理解,mem就是memory的匯流排介面,HellaCacheIO不是在tile/LazyRoCC.scala定義的,所以要自己去找,這裡就不說了。busy定義為output,interrupt定義為output,exception定義為input,這三個訊號後面可以直接用這樣的名字來使用,沒有那些字首的存在。
最後就是RoCCIO,是在RoCCCoreIO的基礎上增加了ptw、fpu_req和fpu_resp這三組訊號,用組作為單位,是因為它們是捆綁的一組埠訊號。ptw要看nPTWPorts這個引數的輸入,如果nPTWPorts=0,那麼久不存在ptw這組埠了,同理,如果沒有usingFPU(這個引數在其他地方定義的),那麼fpu_req、fpu_resp也會沒有,因為我配置的rocket-chip是不存在浮點運算的,所以usingFPU=0,所以全部rocc模組都沒有生成fpu_req和fpu_resp介面。
做一個小結,如果你配置的rocket-chip是使用了浮點運算,且你定製模組功能中需要使用到ptw的,那麼你的rocc模組介面應該包含RoCCCommand散開、RoCCRespons散開、mem、busy、initerrupt、exception、ptw散開、fpu_req散開和fpu_resp散開這麼多的訊號。
下面看一下accumulator和translator模組RTL的埠。
Accumulator:
Translator:
看圖就行了,我就不說明了。
需要注意的是,在scala程式碼中如果RoCCIO中某些訊號你不需要用到,那隻需要將這部分訊號強接false,那麼就會在生成RTL的時候對這些訊號進行優化去掉。也就是說RoCCIO是一個總的類,裡面就申明瞭那麼多的訊號,用不用看你自己的實際情況。
持續ing。
相關文章
- 2-2
- 2-5-2
- MQTT接收HEX(2/2)MQQT
- db2 條帶2DB2
- 2
- Difference between 2>&-, 2>/dev/null, |&, &>/dev/null, >/dev/null, 2>&1devNull
- 使用dataX-stream2stream/stream2mysql/mysql2mysql/mysql2streamMySql
- POI-入門案例(2/2)
- DB2同比環比2(with as )DB2
- Git探祕:深入探索(2/2)Git
- 【caffe2從頭學】:2.學習caffe2
- 深入理解h2和r2dbc-h2
- Oracle Sun Exadata V2 ,V2-2,V2-8 主要配置對比Oracle
- 深入理解 RxJava2:Scheduler(2)RxJava
- Swift 2 2 整合lean cloud Push推送SwiftCloud
- J2EE入門(2) (轉)
- Pandas-2-2-中文文件-二十-
- 終於有人把P2P、P2C、O2O、B2C、B2B、C2C的區別講透了!
- SpringBootb2b2c多使用者商城系統ssmb2b2cSpring BootSSM
- 面試2面試
- nginx(2)Nginx
- 機器學習-2機器學習
- 前端-2前端
- ASM (2)ASM
- nssctf (2)
- CORROSION: 2ROS
- DarkHole: 2
- 2.7(2)
- 機器學習(2)機器學習
- scrapy(2)
- Lecture 2
- Java(2)Java
- 6/2
- Java分解質因數,如輸入8,輸出8=2*2*2Java
- J2SE J2EE J2ME的區別
- P2P技術(2)——NAT穿透穿透
- 如何用JavaScript實現2+2=5?JavaScript
- RxJava2 系列-2:背壓和FlowableRxJava