FPGA開発日記

カテゴリ別記事インデックス https://msyksphinz.github.io/github_pages , English Version https://fpgadevdiary.hatenadiary.com/

Chiselでオリジナルデザインを開発し、Verilogを生成する(1. Chisel-template を生成する)

Chiselを使ってオリジナルデザインを作成してみたい。とりあえず、ディープラーニングをターゲットとして、行列計算のためのモジュールをいろいろ作ってみたい。

まずは、Chisel単体で開発環境とテスト環境を構築するためにはどうしたらよいのだろうか。 いくつか環境を調査した。

Chisel-template を使った環境構築

Chiselを使ってVerilogファイルを生成するためには、

  1. Chiselを記述する
  2. テストを行う
  3. Chisel → (FIRRTL) → FIR → Verilog を生成する

の手順を踏む。このためには、 github で構築されている chisel-template リポジトリを使うのが便利だ。

github.com

Chisel-template を使う場合の注意

まず、Rocket-Chipの環境と共存するのは難しいと考えたほうがよさそうだ。

Rocket-Chipの環境もChiselを使うが、そのときのScala環境などの情報は~/.ivy2というディレクトリに格納されているようだ。 しかし、Chisel-templateとRocket-Chipでは、この~/.ivy2で使用する環境のバージョンが異なるようで、仕方がないので別のVirtualBox環境を構築してしまった。 2つもLinux環境を構築できない場合は、別のアカウントを作ってもよいかもしれない。

FixMadd デザインの開発

ここでは、8bitの入力値を2つ受け取り、その乗算結果を内部に格納された16bitのレジスタと加算する積和演算回路を作ってみよう。

z = z + x *y の回路を作成する。

というわけで作ってみた。Chisel-templateの環境に乗せる形で作成した。GCDのサンプルプログラムがあるので、それをまねする形で作っていく。

github.com

├── src
│   ├── main
│   │   └── scala
│   │       └── fixmadd
│   │           └── FixMadd.scala
│   └── test
│       └── scala
│           └── fixmadd
│               ├── FixMaddMain.scala
│               └── FixMaddUnit.scala

メインのプログラムは以下となる。

/**
  * Compute 8-bit MADD with 16-bit output
  */
class FixMadd extends Module {
  val io = IO(new Bundle {
    val in0       = Input(UInt(8.W))
    val in1       = Input(UInt(8.W))
    val clear     = Input(Bool())
    val in_valid  = Input(Bool())
    val out0      = Output(UInt(16.W))
    val out_valid = Output(Bool())
  })

  val r_acc        = Reg(UInt(16.W))
  val r_mul_result = Reg(UInt(16.W))
  val r_in_valid   = Reg(Bool())
  val r_out_valid  = Reg(Bool())

  r_in_valid  := io.in_valid
  r_out_valid := r_in_valid

  when (io.clear) {
    r_acc        := 0.U
    r_mul_result := 0.U
    r_in_valid   := 0.U
    r_out_valid  := 0.U
  }

  when (io.in_valid) {
    r_mul_result := io.in0 * io.in1
    printf("r_mul_result = %d\n", r_mul_result)
  }

  when (r_in_valid) {
    r_acc := r_acc + r_mul_result
  }

  io.out0 := r_acc
  io.out_valid := r_out_valid
}

シミュレーションとテスト

シミュレーションは以下のようなプログラムを書いて、テストパタンを作成した。

class FixMaddUnitTester(c: FixMadd) extends PeekPokeTester(c) {
  // Madd計算の検証用のテストパタン
  def computeFixMadd(in0: Int, in1: Int, out: Int): (Int) = {
    var resultInt: Int = out + in0 * in1
    val max_val: Int = Math.pow(2, 16).asInstanceOf[Int]
    if (resultInt >= max_val) {
      resultInt = resultInt - max_val
    }
    resultInt
  }

  private val fixmadd = c
  var expected_fixmadd: Int = 0

  // 内部信号のリセット
  poke(fixmadd.io.clear, 1)
  step(1)
  poke(fixmadd.io.clear, 0)

  // i, jの2値を振ってテストパタンを入力する
  for(i <- 1 to 40 by 3) {
    for (j <- 1 to 100 by 7) {
      // in0, in1 を設定する
      poke(fixmadd.io.in0, i)
      poke(fixmadd.io.in1, j)
      // in_valid を設定して 0→1→0 として入力を有効化する
      poke(fixmadd.io.in_valid, 1)
      step(1)
      poke(fixmadd.io.in_valid, 0)
      // Chisel で記述された FixMadd を実行する
      expected_fixmadd = computeFixMadd(i, j, expected_fixmadd)

      step(1)
      // テスト結果を比較する
      expect(fixmadd.io.out0,      expected_fixmadd)
      expect(fixmadd.io.out_valid, 1)
    }
  }
}

テストパタンを実行する

以下のように入力する。

sbt 'testOnly fixmadd.FixMaddTester -- -z Basic'

テストに成功すると、下記のメッセージが出力されて、テストが成功する。

...
[info] [0.444] RAN 421 CYCLES PASSED
[info] FixMaddTester:
[info] FixMadd
[info] FixMadd
[info] Basic test using Driver.execute
[info] - should be used as an alternative way to run specification
[info] using --backend-name verilator
[info] running with --is-verbose
[info] running with --fint-write-vcd
[info] using --help
[info] ScalaTest
[info] Run completed in 3 seconds, 77 milliseconds.
[info] Total number of tests run: 1
[info] Suites: completed 1, aborted 0
[info] Tests: succeeded 1, failed 0, canceled 0, ignored 0, pending 0
[info] All tests passed.
[info] Passed: Total 1, Failed 0, Errors 0, Passed 1
[success] Total time: 29 s, completed Jan 8, 2018 11:37:15 PM

Verilogを生成する

以下のように入力すると Verilog コードが生成される。

sbt test

確認してみよう。

$ find . -name *.v
./test_run_dir/fixmadd.FixMaddTester847075120/FixMadd.v
./test_run_dir/fixmadd.FixMaddTester2058266144/FixMadd.v
  • test_run_dir/fixmadd.FixMaddTester847075120/FixMadd.v
module FixMadd(
  input         clock,
  input         reset,
  input  [7:0]  io_in0,
  input  [7:0]  io_in1,
  input         io_clear,
  input         io_in_valid,
  output [15:0] io_out0,
  output        io_out_valid
);
  reg [15:0] r_acc; // @[FixMadd.scala 20:25]
  reg [31:0] _RAND_0;
  reg [15:0] r_mul_result; // @[FixMadd.scala 21:25]
  reg [31:0] _RAND_1;
  reg  r_in_valid; // @[FixMadd.scala 22:25]
  reg [31:0] _RAND_2;
...

Vivadoで論理合成試行

Vivadoで論理合成を試行してみた。特に問題なく合成できるようだ。

github.com

  • タイミング
------------------------------------------------------------------------------------------------
| Design Timing Summary
| ---------------------
------------------------------------------------------------------------------------------------

    WNS(ns)      TNS(ns)  TNS Failing Endpoints  TNS Total Endpoints      WHS(ns)      THS(ns)  THS Failing Endpoints  THS Total Endpoints     WPWS(ns)
    -------      -------  ---------------------  -------------------      -------      -------  ---------------------  -------------------     --------
      2.284        0.000                      0                   49        0.152        0.000                      0                   49        2.000
  • 面積
+-------------------------+------+-------+-----------+-------+
|        Site Type        | Used | Fixed | Available | Util% |
+-------------------------+------+-------+-----------+-------+
| Slice LUTs*             |   89 |     0 |     53200 |  0.17 |
|   LUT as Logic          |   89 |     0 |     53200 |  0.17 |
|   LUT as Memory         |    0 |     0 |     17400 |  0.00 |
| Slice Registers         |   34 |     0 |    106400 |  0.03 |
|   Register as Flip Flop |   34 |     0 |    106400 |  0.03 |
|   Register as Latch     |    0 |     0 |    106400 |  0.00 |
| F7 Muxes                |    0 |     0 |     26600 |  0.00 |
| F8 Muxes                |    0 |     0 |     13300 |  0.00 |
+-------------------------+------+-------+-----------+-------+

関連記事

"FPGA開発日記"でのChiselを取り扱った記事。