ChiselはScalaをベースとしたハードウェア記述言語なので、Verilog-HDLではあまり見かけることのない記述ができる。
最近使っているChiselの便利な技法のいくつかをまとめてみる。
Vec
の中身を.reduc
を使ってリダクションする
Vec
にはreductionなどの記法が用意されている。具体的には、あまり説明のないAPI一覧の資料を見てほしいのだが、
https://chisel.eecs.berkeley.edu/api/3.1.0/chisel3/core/Vec.htmlchisel.eecs.berkeley.edu
例えば、こんな感じで書く。
class map_test(WIDTH: Int = 32) extends Module { val io = IO(new Bundle { val in_val = Input (Vec(WIDTH, UInt(16.W))) val reduc = Output(UInt(16.W)) }) io.reduc := io.in_val.reduce(_ +& _) }
入力信号の16bit×WIDTHのベクトル形式の信号を受け取り、それらのすべての要素を加算(+&
はビット拡張を行いながら加算する)してその結果を返す。
これは+&
以外でも、論理演算などでも使える。 reduce(_ | _)
など。
Vec
の内容すべてに処理を適用するための.map
Mapを使うと、すべての要素に処理を適用できる。例えば、以下はWIDTH長のベクトル入力に対してすべてNOT演算を適用する。
class map_test(WIDTH: Int = 32) extends Module { val io = IO(new Bundle { val in_bool = Input (Vec(WIDTH, Bool())) val not_out = Output(Vec(WIDTH, Bool())) }) io.not_out := io.in_bool.map(x => ~x) }
in_bool
のすべてのベクトルに対して、NOT演算を適用してその結果をio.not_out
に渡している。
- Mapでベクトルの要素を取り出して、さらにReducする
.map
は上記のような処理の適用だけでなく、ベクトル内の要素の取り出しにも使える。例えば、以下はValidIO
信号の中のbits
要素(ValidIO
はvalid
とbits
の2種類から構成されているデータ型である)を取り出して、それらをすべてのベクトルに対してreduc
する。
class map_test(WIDTH: Int = 32) extends Module { val io = IO(new Bundle { val in_validio = Input(Vec(WIDTH, ValidIO(UInt(16.W)))) val out_validio = Output(UInt(16.W)) }) io.out_validio := io.in_validio.map(x => x.bits).reduce(_ +& _) }
map
により要素の取り出しを行い、その結果に対してreduc
を適用した。
このように、簡単な処理であればVerilog-HDLのようにfor文を使わずに処理を実現できる。