このエントリはHDL Advent Calendarの20日目のものです。
同時に、2015/08/24-25にクパチーノでおこなわれたHot Chips 27カンファレンスへ参加し、そこで紹介されていたRISC-Vに興味を持った関連エントリです。
このカンファレンスではQUALCOMMの新DSPアーキテクチャ発表や5Gネットワークに関する講演、MicrosoftのSmartNICなど興味深いトピックが多く扱われていました。
この中で私が最も強く関心を持ったのがScalaからの高位合成ツールであるChiselです。
やることは
ともかく、以下のようなコードが書けました。テストコードもゴリゴリと書いています。
テストモジュールをもりもり作りながら進めるスタイルが定着するのもいいなっという感じがしますね。
生成されていますね。
タイミング検証とテストコード実行をおこなうためのエミュレータ用C++コードは次のとおり生成されました。
それには入力用のスイッチ8つと出力用のLED5つを制御する必要があるのですが、これPmod(手持ちのMicroZedは100ピンの高周波回路用コネクタ以外には基本的にPmodコネクタぐらいしかないので)ではギリギリ足りないな? と気付いて頭を抱えたりしている昨今です。
趣味で作るハードウェアでも「ScalaコードをコミットしたらJenkinsで速やかにタイミングチェックまでおこなって、結果が怪しければ即座にエラーメールが届く」というワークフローになるとずいぶん楽しいと思いませんか。
また、今回Chiselを使ってみた結果、Scalaを勉強する機会にもなりました。これまでScalaといえばコンパイルが遅い言語でなんとなくHaskellのほうがかっこいい、ぐらいの印象でいたのですが、ちゃんと学ぶ気力が湧いてきたのでとてもよかったと思います。
Chiselの続編はまたそのうち。明日の担当はikwzmさんです。
同時に、2015/08/24-25にクパチーノでおこなわれたHot Chips 27カンファレンスへ参加し、そこで紹介されていたRISC-Vに興味を持った関連エントリです。
このカンファレンスではQUALCOMMの新DSPアーキテクチャ発表や5Gネットワークに関する講演、MicrosoftのSmartNICなど興味深いトピックが多く扱われていました。
この中で私が最も強く関心を持ったのがScalaからの高位合成ツールであるChiselです。
Chiselの概要
Chiselは次のような特徴を持ちます。- 入力言語にScalaを用いたオープンソースの高位合成ツールキット
- 出力はVerilog
- クロック同期保証つきのシミュレータコード(C++)を書き出すことができ、これによって大規模チップの開発イテレーションすら比較的高速に回せるとしている
- UC Berkeleyで開発され、RISC-Vの開発に利用されている
とにかくChiselを触ってみよう
何はともあれ、半加算器を作るところからスタートしてみます。やることは
- 入力値同士を足してキャリーを発生させる
- .otherwiseの最後のブレースを抜かしてコンパイルエラー
- BoolをBOOLと書いてコンパイルエラー
- := を =としていて再定義エラー
- Bool宣言したものにそのままのboolean値を突っ込もうとして型ミスマッチエラー(Bool(true)な必要ある)
- implicit type conversion入れといて欲しい・・・
- expectにboolean値もBool(...)も渡せない問題
- ここはBitsとして扱うしかなさそう
ともかく、以下のようなコードが書けました。テストコードもゴリゴリと書いています。
package Td4Scala import Chisel._ class HalfAdder extends Module { val io = new Bundle { val in0 = Bool(INPUT) val in1 = Bool(INPUT) val out = Bool(OUTPUT) val carry = Bool(OUTPUT) } when (io.in0 ^ io.in1) { io.out := Bool(true) } .otherwise { io.out := Bool(false) } when (io.in0 && io.in1) { io.carry := Bool(true) } .otherwise { io.carry := Bool(false) } } class HalfAdderTests(c: HalfAdder) extends Tester(c) { poke(c.io.in0, false) poke(c.io.in1, false) step(1) expect(c.io.out, 0) expect(c.io.carry, 0) // poke(c.io.in0, true) poke(c.io.in1, false) step(1) expect(c.io.out, 1) expect(c.io.carry, 0) // poke(c.io.in0, false) poke(c.io.in1, true) step(1) expect(c.io.out, 1) expect(c.io.carry, 0) // poke(c.io.in0, true) poke(c.io.in1, true) step(1) expect(c.io.out, 0) expect(c.io.carry, 1) }
Verilogへ出してみる
書けたScalaソースファイルをScalaの流儀に従ってbuild.sbtファイルの定義のもとビルドしていくのですが、少々うまくいかないところもありました。- Makefileのターゲットを変えるとコマンド出力的にはできそうだが実際には.vファイルが生成されない
- vpi_user.hが無いと怒られる
- ハーネス側がだめっぽい?
- 無駄オプションを削ってコンパイルオプションを--backend vだけにする
- 普通に通った
- やっぱハーネスかー。これは後で調べる
module HalfAdder( input io_in0, input io_in1, output io_out, output io_carry ); wire T0; wire T1; wire T2; wire T3; assign io_carry = T0; assign T0 = T1 ? 1'h1 : 1'h0; assign T1 = io_in0 & io_in1; assign io_out = T2; assign T2 = T3 ? 1'h1 : 1'h0; assign T3 = io_in0 ^ io_in1; endmodule
タイミング検証とテストコード実行をおこなうためのエミュレータ用C++コードは次のとおり生成されました。
#include "HalfAdder.h" // ... 略 ... void HalfAdder_t::clock_lo ( dat_t<1> reset ) { val_t T0; { T0 = HalfAdder__io_in0.values[0] ^ HalfAdder__io_in1.values[0];} val_t T1; { T1 = TERNARY(T0, 0x1L, 0x0L);} { HalfAdder__io_out.values[0] = T1;} val_t T2; { T2 = HalfAdder__io_in0.values[0] & HalfAdder__io_in1.values[0];} val_t T3; { T3 = TERNARY(T2, 0x1L, 0x0L);} { HalfAdder__io_carry.values[0] = T3;} } // ... 略 ...
この先
半加算器だけではなんとも悲しいので、ひとまずこのまま4bit同士の加算をできるところまで拡張してみて、手持ちのFPGA評価ボードで計算の途中経過をLED出力できるようにしてみようと思っています。それには入力用のスイッチ8つと出力用のLED5つを制御する必要があるのですが、これPmod(手持ちのMicroZedは100ピンの高周波回路用コネクタ以外には基本的にPmodコネクタぐらいしかないので)ではギリギリ足りないな? と気付いて頭を抱えたりしている昨今です。
Scalaで電子回路、楽しいかもしれない
Chiselが高位合成ツールセットとして楽しいポイントは、概要にも書いたようにクロック同期保証付きのエミュレータ用コード生成をおこなってくれるあたりです。小さなものを書いている中でもすでにcpp経由で開発マシン上のバイナリを吐き出してサクサク実行できることの楽さは感じつつあります*1し、これはきっと扱う対象が大規模化するにつれて更に嬉しくなっていくのでしょう。趣味で作るハードウェアでも「ScalaコードをコミットしたらJenkinsで速やかにタイミングチェックまでおこなって、結果が怪しければ即座にエラーメールが届く」というワークフローになるとずいぶん楽しいと思いませんか。
また、今回Chiselを使ってみた結果、Scalaを勉強する機会にもなりました。これまでScalaといえばコンパイルが遅い言語でなんとなくHaskellのほうがかっこいい、ぐらいの印象でいたのですが、ちゃんと学ぶ気力が湧いてきたのでとてもよかったと思います。
Chiselの続編はまたそのうち。明日の担当はikwzmさんです。
[*1] 特に私の場合はScalaにもVerilogにもさほど慣れていないので、コードの正しさを判定するためのセカンドオピニオンとしてC++コードを利用できる安心感は大きいです。
0 件のコメント:
コメントを投稿