Scalaの文法は少しわかってきたので、とりあえず今のタイミングでChiselの勉強も始めて行こうと思う。まずは環境構築!!ということになるが、それを行うにあたって情報収集を行った内容を記載していく。
Chiselって
とりあえず本家のサイトをチェック。
Chisel: Constructing Hardware in an Scala Embedded Language
そして毎度のようにWikipediaさんをチェックしてみる。
Chiselは、デジタル回路設計用の、オープンソースのハードウェア記述言語(HDL: Hardware Description Language)の一種である。カリフォルニア大学バークレー校で開発が行われている。Chiselは、Scalaの内部DSLとして実装されている。 Chisel - Wikipedia
ものすごーーーくシンプルな概要ですこと。これだったら本家のものを引っ張ったほうが良さそう。ということで本家サイトAbout Chiselを(適当に)訳したものを記載。
ChiselはUCバークレーで開発されたオープンソースのハードウェア言語でパラメタライズされたジェネレータを使うことで高度なハードウェアデザインをサポートするDSLである。 - ハードウェア記述言語(かつC言語をゲートにするものではない) - Scalaに埋め込まれたもの(DSL) - 代数による構築と結線 - 抽象データ型とインターフェース - 大部分の接続 - 階層的でオブジェクト指向による機能の構築 - Scalaのメタプログラミングによる高度なパラメタライズ - DSLレイヤーのサポート - 浮動小数点を含む多くの標準ライブラリ - 複数のクロックドメイン - 標準のASICやFPGAで使用可能なローレベルのVerilogコードの生成 - 修正BSDライセンスの下にオープンソースでgithubに公開されている - 完全なドキュメント - 使用者による成長中のコミュニティ
これはこれでシンプルすぎて(&勉強してないこともあり)わからん。勉強しながら、意味が理解できてしっくりする訳が浮かんだら更新することにしよう。
サンプルコード
同じページにサンプルコードとして以下の4つが紹介されている
- GCD : 最大公約数
- MaxN : 最大値の算出
- Mul : 乗算
- Adder : 加算
環境を構築した後、再度詳しく見ていくがとりあえずコードをペタリ。
GCD
import chisel3._ class GCD extends Module { val io = IO(new Bundle { val a = Input(UInt(32.W)) val b = Input(UInt(32.W)) val e = Input(Bool()) val z = Output(UInt(32.W)) val v = Output(Bool()) }) val x = Reg(UInt(32.W)) val y = Reg(UInt(32.W)) when (x > y) { x := x -% y } .otherwise { y := y -% x } when (io.e) { x := io.a; y := io.b } io.z := x io.v := y === 0.U }
とりあえずScalaの勉強をしてみたおかげで、なんとなくは読めるのは良かった!まだ推測でしか無いが、こんな感じっぽい。
- Verilogの
module
はModule
を継承したScalaのclass
として定義 input
/output
は同様にIO
クラスの中にBundle
クラスを与えて定義する- Verilogの
reg
宣言はReg
でその時のビット幅はUInt
クラス。この場合は32bitっぽい。 when
で条件分岐(調べてみたらScalaのものっぽいので後で別途紹介予定)assign foo = bar
とかってやってたのはio.foo := bar
になりそう。
MaxN
import chisel3._ class MaxN(val n: Int, val w: Int) extends Module { private def Max2(x: UInt, y: UInt) = Mux(x > y, x, y) val io = IO(new Bundle { val ins = Input(Vec(n, UInt(w.W))) val out = Output(UInt(w.W)) }) io.out := io.ins.reduceLeft(Max2) }
MaxNなので、N個の値の中から最大値を返すものみたいだが、実際にはMax2
という2値の比較器をio.ins.reduceLeft(Max2)
で処理しているだけのようだ。
これで書けちゃうのか。。。
Mul
import chisel3._ import scala.collection.mutable.ArrayBuffer /** Four-by-four multiply using a look-up table. */ class Mul extends Module { val io = IO(new Bundle { val x = Input(UInt(4.W)) val y = Input(UInt(4.W)) val z = Output(UInt(8.W)) }) val muls = new ArrayBuffer[UInt]() // -------------------------------- \\ // Calculate io.z = io.x * io.y by // building filling out muls // -------------------------------- \\ for (i <- 0 until 16) for (j <- 0 until 16) muls += (i * j).U(8.W) val tbl = Vec(muls) io.z := tbl((io.x << 4.U) | io.y) }
乗算だけど、最初の2重for
ループでLUT作ってる気配。
Adder
import chisel3._ import chisel3.util._ //A n-bit adder with carry in and carry out class Adder(val n:Int) extends Module { val io = IO(new Bundle { val A = Input(UInt(n.W)) val B = Input(UInt(n.W)) val Cin = Input(UInt(1.W)) val Sum = Output(UInt(n.W)) val Cout = Output(UInt(1.W)) }) //create an array of FullAdders val FAs = Array.fill(n)(Module(new FullAdder()).io) val carry = Wire(Vec(n+1, UInt(1.W))) val sum = Wire(Vec(n, Bool())) //first carry is the top level carry in carry(0) := io.Cin //wire up the ports of the full adders for (i <- 0 until n) { FAs(i).a := io.A(i) FAs(i).b := io.B(i) FAs(i).cin := carry(i) carry(i+1) := FAs(i).cout sum(i) := FAs(i).sum.toBool() } io.Sum := Cat(sum.reverse) io.Cout := carry(n) }
これはほんとに加算器だな。それもFull Adder使ったやつ。FA間の接続がfor
ループになってるのは素敵。
プログラミングを始めるにあたって
という、項目があったのでそれも一緒に記載しつつ学習に役に立ちそうなサイトをメモっていく。
Chiselは公式のMaven repo.からJARsファイルのコレクションとしてリリースされている。[Generator Bootcamp](https://github.com/ucb-bar/generator-bootcamp)にJupyter notebookを使った自分のペースで実行可能なチュートリアルが公開されている。これを使えばChiselをすぐに実行可能だ。
ということで、役に立ちそうなリンクを(これも全部Chiselの公式サイト)に載っている情報。
- Generator Bootcamp
- DAC2012 Introduction Paper
- DAC2012で発表されたChiselmp紹介の論文
- Chisel Tutorial repository
- Chisel3: The latest version of Chisel
- これはChiselの最新バージョンであるChisel3のWiki。Chisel3のユーザーガイドや、Chisel2との違い、cookbookなどが公開されている。
- これから勉強していくのでChisel3を使おうと思っている。なのでユーザーガイドはとっても役に立ちそう。
- The RISC-V sodor processors in Chisel
とここまで、ざっとChisel自体の情報収集を行った結果をつらつらと書いてみた。
次回からはGenerator Bootcampを使ってChiselの環境構築から実際の勉強をスタートしていきたい。