3
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Chiselコンパイルのあれこれと回路の動作テスト(Chisel勉強会3)

Last updated at Posted at 2019-12-03

はじめに

筆者は失恋でめんたるぼろぼろなので、間違いなどがありましたら優しく教えてくださいまし
すからは嫌になってきた

Chiselのビルド方法

Chiselをビルドするにはpart1で環境を整えたsbt(Simple Build Tool)
コマンドというものを使用していきます

Chiselまわりのライブラリをインターネットから引っ張ってきてビルドを自動的にやってくれるもの

ビルドに失敗したときは、インターネットの接続状態とハードウェアのデザインを見直す必要がある

ChiselやScalaのバージョンをいじりたいときはbuild.sbt(Chiselプロジェクトの一番親ディレクトリに書き込む設定ファイル)をカスタマイズすることで可能

全然シンプルじゃないけどこれの使い方をいかに記していきたいと思います

sbtのあれこれ

完全に余談ではあるが、sbtコマンドはMavenというビルドツールを派生させたものらしく、Java -> Maven -> sbt と作られていったのだそう

より深く知りたかったらMavenってやつを知る必要あり?(自分はめんどくさがりなのでパス)

プロジェクトの構造は以下のようになっているのがベース

.
├── build.sbt
├── project
│   ├── build.properties
│   ├── plugins.sbt
│   ├── project
│   │   └── target
│   └── target
├── src
│   ├── main
│   │   ├── java
│   │   ├── resources
│   │   ├── scala
│   └── test
│       ├── java
│       ├── resources
│       ├── scala
└── target

Chiselを用いたライブラリの作成

自作のクラスの作成の記述方法は以下のようになります

OriginalClass.scala
// ライブラリ名の定義
package mypack

// chiselのクラス一覧を全てインポート
import chisel3._

// オリジナルのクラスの定義
class ABC extends Modules{
    val io = IO(new Bundle{})
}
ImportClass.scala
import mypack._

// ABCクラス単体でのインポート方法
// import mypack.ABC

class ABCUser extends Module{
    val io = IO(new Bundle{})
    
    // オリジナルクラスの呼び出し
    val abc = Module(new ABC())
}

うん、Javaと変わんない

Chiselでのテストベンチ記述方法

言うまでもないですが、ハードウェアのファイルに入力を与えて結果と予想を照らし合わせるためのファイルをテストベンチといいます

ChiselではテストベンチをPeekPokeTesterというもので値をぶっこんでいきます(なんか名前かわいい)

実際にテストベンチを以下のように作っていきます

書き方1つめ

Target_tb1.scala
import chisel3._
import chisel3.iotesters._

class DeviceUnderTest extends Module {
    val io = IO(new Bundle {
        val a = Input(UInt (2.W))
        val b = Input(UInt (2.W))
        val out = Output(UInt (2.W))
    })
    
    io.out := io.a & io.b
}

object Test extends App {
    iotesters.Driver.execute(args, () => new DeviceUnderTest){
        c => new PeekPokeTester(c) {
            poke(dut.io.a, 0.U)
            poke(dut.io.b, 1.U)
            step (1)
            println("Result is: " + peek(dut.io.out).toString)

            poke(dut.io.a, 3.U)
            poke(dut.io.b, 2.U)
            step (1)
            println("Result is: " + peek(dut.io.out).toString)
        }
    }
}

書き方2つめ

Target_tb2.scala
object Test extends App {
    iotesters.Driver.execute(args, () => new DeviceUnderTest){
        c => new PeekPokeTester(c) {
            poke(dut.io.a, 3.U)
            poke(dut.io.b, 1.U)
            step (1)
            expect(dut.io.out, 1)

            poke(dut.io.a, 2.U)
            poke(dut.io.b, 0.U)
            step (1)
            expect(dut.io.out, 0)
        }
    }
}

書き方1では結果が全て出力されるが、2では先に答えを入れておいて正しい答えが出力されたときにSuccessと表示するものになっている

ちなみにDUTはdesign under testって意味だお

いざ実行・・・の前にbuild.sbtに以下を付け足さなきゃいけないみたい

build.sbt
// バージョンを指定してchiselのiotestersをインストール
// 他のライブラリを使用するためには初回のダウンロードする必要があり?(よーわかってない)

libraryDependencies += "edu.berkeley.cs" %% "chisel-iotesters" % "1.3.1"

実行

// 1つめのテスト

$ sbt run

[info] running Test 
[info] [0.001] Elaborating design...
[info] [0.517] Done elaborating.
Total FIRRTL Compile Time: 205.3 ms
file loaded in 0.032897348 seconds, 7 symbols, 3 statements
[info] [0.000] SEED 1575360902041
[info] [0.002] Result is: 0
[info] [0.002] Result is: 2
test DeviceUnderTest Success: 0 tests passed in 7 cycles in 0.008071 seconds 867.28 Hz
[info] [0.003] RAN 2 CYCLES PASSED

// 2つめのテスト

$ sbt run

[info] running Test 
[info] [0.001] Elaborating design...
[info] [0.520] Done elaborating.
Total FIRRTL Compile Time: 204.3 ms
file loaded in 0.032164604 seconds, 7 symbols, 3 statements
[info] [0.000] SEED 1575361065328
test DeviceUnderTest Success: 2 tests passed in 7 cycles in 0.007838 seconds 893.12 Hz
[info] [0.003] RAN 2 CYCLES PASSED

できたあああああああああああああああああああうおおおおおおおおおおおおおおおおおおおおおおおお

回路の評価の際は1つめでゆる〜いチェックして、2つめで回路が完璧に動くかを判断するといいかも?

Packageとテストを組み合わせてみる

packageでライブラリ生成して実際にimportしたものを評価してみましょう!

Package.scala
package pack

import chisel3._
import chisel3.iotesters._

class DeviceUnderTest extends Module {
    val io = IO(new Bundle {
        val a = Input(UInt (2.W))
        val b = Input(UInt (2.W))
        val out = Output(UInt (2.W))
    })

    io.out := io.a & io.b
}
Main.scala
import pack._

import chisel3._
import chisel3.Driver
import chisel3.iotesters._

class Main extends Module {
    val io = IO(new Bundle {
        val a = Input(UInt(2.W))
        val b = Input(UInt(2.W))
        val out = Output(UInt(2.W))
    })
    
    // 実際に回路を使用する場合はModuleとして呼び出す必要がある
    val d = Module(new DeviceUnderTest())

    d.io.a := io.a
    d.io.b := io.b
    io.out := d.io.out
}

object Test extends App {
    iotesters.Driver.execute(args, () => new Main){
        c => new PeekPokeTester(c) {
            poke(dut.io.a, 3.U)
            poke(dut.io.b, 1.U)
            step (1)
            println("Result is: " + peek(dut.io.out).toString)

            poke(dut.io.a, 2.U)
            poke(dut.io.b, 0.U)
            step (1)
            println("Result is: " + peek(dut.io.out).toString)
        }
    }
}

まとめ

もう主要な機能はわかってきたから、とりあえず今回で締めかな?
あとはアーキテクチャやらアルゴリズムの理解の問題だと思われるので!
また重要なことがあればまとめます!
でも実際にChiselでRISCの設計をしてないから、とりあえずMipsでも作ってみよーかな

参考文献

3
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?