ハードウェアの気になるあれこれ

技術的に興味のあることを調べて書いてくブログ。主にハードウェアがネタ。

ハードウェア記述言語Chisel - 情報収集

スポンサーリンク

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の勉強をしてみたおかげで、なんとなくは読めるのは良かった!まだ推測でしか無いが、こんな感じっぽい。

  • VerilogmoduleModuleを継承したScalaclassとして定義
  • input/outputは同様にIOクラスの中にBundleクラスを与えて定義する
  • Verilogreg宣言は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
    • Jupyter notobookを使って実行しつつ学べるチュートリアル
    • ざっと中身を見てみたところ、Scalaの簡単な説明から始まり、Chisel環境の構築、簡単なモジュールの作成などなど一通りのことが体験できそうなので、次回以降はこれをこなしていく感じにしよう。
  • DAC2012 Introduction Paper
    • DAC2012で発表されたChiselmp紹介の論文
  • Chisel Tutorial repository
    • UCバークレーが公開してくれているチュートリアル。実際に動かせる環境と練習問題が用意されている
    • とりあえずBootcamp触ってからこっちにも取り組んでみよう
  • Chisel3: The latest version of Chisel
    • これはChiselの最新バージョンであるChisel3のWiki。Chisel3のユーザーガイドや、Chisel2との違い、cookbookなどが公開されている。
    • これから勉強していくのでChisel3を使おうと思っている。なのでユーザーガイドはとっても役に立ちそう。
  • The RISC-V sodor processors in Chisel
    • Chiselで書かれた"シンプルな"RISC-Vの実装のgithubリポジトリ
    • 今やっているSCR1の解析と共にこっちも見ていきたい

とここまで、ざっとChisel自体の情報収集を行った結果をつらつらと書いてみた。

次回からはGenerator Bootcampを使ってChiselの環境構築から実際の勉強をスタートしていきたい。