Chisel 手册(中文part2)
Chisel 手冊(中文part2)
作者:Jonathan Bachrach, Huy Vo, Krste Asanovi?;? EECS Department, UC Berkeley?
譯者:智能物聯(CSDN)?
?
6?Updateables
當描述wire和state節點的運作時,我們通常為輸出端口指定一系列的條件更新,然后用若干獨立語句把這些更新散播出去。舉例來說,Data節點的輸出可以立刻引用,但是輸入可以延后設置。Updateable表示一個條件更新節點,它累積針對節點的路徑,然后生成mux并對這些電路的路徑進行組合邏輯運算。
?
abstract?class?Updateable?extends?Node?{?//?conditional?reads?def?reads:?Queue[(Bool,?UInt)]?//?conditional?writes?def?writes:?Queue[(Bool,?UInt,?Node)]?//?gen?mux?integrating?all?conditional?writes?def?genMuxes(default:?Node)?override?def?:=?(x:?Node):?this.type?
}
Chisel提供條件更新規則,用when語句支持這類時序邏輯描述:
?
object?when?{?def?apply(cond:?Bool)(block:?=>?Unit):?when?
}?class?when?(prevCond:?Bool)?{?def?elsewhen?(cond:?Bool)(block:?=>?Unit):?when?def?otherwise?(block:?=>?Unit):?Unit?
}
when語句使用動態作用域scope來操縱全局條件棧,因此,when語句生成新的條件,將在函數調用路徑內一直起作用。舉個例子:
?
def?updateWhen?(c:?Bool,?d:?Data)?=?when?(c)?{?r?:=?d?}?
when?(a)?{?updateWhen(b,?x)?
}
與下列相同:
?
when?(a)?{?when?(b)?{?r?:=?x?}?
}
Chisel為其他常用類型的條件更新提供一些語法糖:
?
def?unless(c:?Bool)(block:?=>?Unit)?=?when?(!c)?{?block?)
還有
?
def?otherwise(block:?=>?Unit)?=?when?(Bool(true))?{?block?}
我們介紹了switch語句,用于根據一系列普通key的比較結果進行條件更新:
?
def?switch(c:?UInt)(block:?=>?Unit):?Unit?def?is(v:?Bool)(block:?=>?Unit)
?
7?Forward Declarations
純組合電路不允許出現節點的閉環。如果發現閉環,Chisel會報錯。因為不存在閉環,所以可以生成單方向的合法的組合邏輯電路,通過添加新的節點,輸入取自那些已定義的節點。時序電路具有節點之間的反饋,所以有時候必須在定義生成某個節點之前聲明這個輸出。因為Scala順序執行程序語句,我們一般讓數據節點作為wire立即引用,但是它們的輸入延后設置。舉例來說,在一個簡單的CPU中,我們需要預先聲明pcPlus4和brTarget這兩個wires,以便后續引用:
?
val?pcPlus4??=?UInt()?
val?brTarget?=?UInt()?
val?pcNext???=?Mux(pcSel,?brTarget,?pcPlus4)?
val?pcReg????=?RegUpdate(pcNext)?
pcPlus4?????:=?pcReg?+?UInt(4)?
...?
brTarget????:=?addOut
連線運算符 := 用于連接pcReg與addOut。所有的賦值完成,所有的電路都計算以后,如果還有前向聲明還沒有被賦值的話,系統將會報告錯誤。
?
8?Regs
Chisel支持的最簡單的狀態單元是正沿觸發的寄存器,如下所示:
?
object?Reg?{?def?apply[T?<:?Data]?(data:?T,?next:?T?=?null,?init:?T?=?null):?T?
}?object?RegNext?{?def?apply[T?<:?Data]?(next:?T,?init:?T?=?null):?T?
}?object?RegInit?{?def?apply[T?<:?Data]?(init:?T):?T?
}?class?Reg?extends?Updateable
創建方法如下所示:
?
val?r1?=?RegUpdate(io.in)?
val?r2?=?RegReset(UInt(1,?8))?
val?r3?=?RegUpdate(io.in,?UInt(1))?
val?r4?=?Reg(UInt(width?=?8))
復位值resetVal是隱含的reset信號為真時候所取的reg值。
?
9?Mems
Chisel通過Mem語句支持RAM。寫入Mem是正沿觸發,讀取是組合邏輯或者正沿觸發。
?
object?Mem?{?def?apply[T?<:?Data](depth:?Int,?gen:?=>?T,?seqRead:?Boolean?=?false):?Mem?
}?class?Mem[T?<:?Data](gen:?()?=>?T,?depth:?Int,?seqRead:?Boolean?=?false)?extends?Updateable?{?def?apply(idx:?UInt):?T?
}
Mems內部的Ports被賦值UInt的索引 。一個具有一個寫端口和兩個組合邏輯讀端口的32-entry的寄存器組描述如下:
?
val?rf?=?Mem(32,?UInt(width?=?64))?
when?(wen)?{?rf(waddr)?:=?wdata?}?
val?dout1?=?rf(waddr1)?
val?dout2?=?rf(waddr2)
如果設置可選參數seqRead,當Reg被賦予Mem的輸出,Chisel會生成時序讀取端口。一個單口讀,單口寫的SRAM可以描述如下:
?
val?ram1r1w?=?Mem(1024,?UInt(width?=?32),?seqRead?=?true)?
val?dout?=?Reg(UInt())?
when?(wen)?{?ram1r1w(waddr)?:=?wdata?}?
when?(ren)?{?dout?:=?ram1r1w(raddr)?}
在when語句鏈條中,如果讀和寫的條件互斥,將生成單端口的SRAM。
?
val?ram1p?=?Mem(1024,?UInt(width?=?32),?seqRead?=?true)?
val?dout?=?Reg(UInt())?
when?(wen)?{?ram1p(waddr)?:=?wdata?}?
.elsewhen?(ren)?{?dout?:=?ram1p(raddr)?}
如果同一個Mem地址在同一個clock邊沿同步讀寫,或者如果sequential read使能被清除,讀數據是用戶自定義的?
Mem 也支持寫入mask,以便部分字節寫入。?
?
val?ram?=?Mem(256,?UInt(width?=?32))?
when?(wen)?{?ram.write(waddr,?wdata,?wmask)?}
?
10?Ports
端口繼承自Data節點,用于硬件模塊的接口。端口是原始Data對象的有方向版本。端口方向定義如下:
?
trait?PortDir?
object?INPUT??extends?PortDir?
object?OUTPUT?extends?PortDir
復合端口可以遞歸創建,使用vec或者bundle組合簡單的子端口。
?
11?Modules
在Chisel中,模塊Module與Verilog中的模塊非常相似,模塊定義了一個被生成電路的層次結構。模塊的命名空間可以被下游的工具來訪問,用于調試和物理布局。一個用戶自定義模塊被定義成一個class:
- 繼承自Module,
- 包含一個接口Bundle,保存于一個io,
- 在構造器中用連線連接子電路。
用戶通過module的子類來寫自己的模塊:
?
abstract?class?Module?{?val?io:?Bundle?var?name:?String?=?""?def?compileV:?Unit?def?compileC:?Unit?
}
定義它們自己的io。下例定義了一個雙輸入Mux的模塊:
?
class?Mux2?extends?Module?{?val?io?=?new?Bundle{?val?sel?=?Bool(INPUT)?val?in0?=?Bool(INPUT)?val?in1?=?Bool(INPUT)?val?out?=?Bool(OUTPUT)?}?io.out?:=?(io.sel?&?io.in1)?|?(~io.sel?&?io.in0)?
}
:= 賦值運算符,用于module內部,是Chisel的一個特殊運算符,連接左側的輸入到右側的輸出。典型地用于連接輸出端口和它們的定義。
<> 運算符成捆連接兄弟模塊之間的相反的接口,或者父子模塊之間的相同的接口。成捆連接使用路徑名匹配方式連接葉端口。連接只在port非無效的時候進行,允許用戶重復成捆連接那些只有部分使用的接口。所有的連接完成以后電路將被優化,Chisel 如果發現端口不止一個連接,將會發出警告。
模塊內部的節點和子模塊的命名,由C++或者Verilog后端負責,取自模塊的域名,使用Scala內審機制。使用函數setName()也可以設置節點和子模塊的名字。
總結
以上是生活随笔為你收集整理的Chisel 手册(中文part2)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: ApiDoc官方文档
- 下一篇: css中table标签详解(一)