2022年11月24日に開催した、「実践的!FPGA開発セミナーvol.16」の当日資料です。
Copyright© Fixstars Group実践的!FPGA開発セミナーvol.162022/11/24 18:00~
View Slide
Copyright© Fixstars GroupFPGA の論理を Chisel でゴリゴリ開発してみた話
Copyright© Fixstars GroupWho I amYoshitakaTAKEMOTO竹本 義孝ソリューション第四事業部シニアエンジニア
Copyright© Fixstars GroupVerilog しんどい4
Copyright© Fixstars GroupVerilog 開発の不満● Verilog 言語の機能が低い○ System Verilog では assertion や interface やらいろいろ使える!!■ SV の機能が使えるかどうか割と環境依存● C社 で使えた SV が I社 でコンパイルできなかった思い出■ Verilog ならどこでも安定● Verilog の開発支援環境が貧弱○ 現在は LSP を開発されている方もおられます■ https://github.com/imc-trading/svlangserver■ https://github.com/dalance/svls○ VSCode 使いなんですけど、良い設定ないですかね● 論理は楽しいけど Verilog は何も楽しくない○ 個人の感想です。効果には個人差があります5
Copyright© Fixstars GroupChisel3 でゴリゴリ開発してみた話● 最近 Vivado/Vitis HLS ばかりなので、クロック単位の論理を書きたかった○ 友人とちょっと FPGA 開発する話になりました(趣味)● しかしVerilog は書きたくない● System Verilog は環境ごとに何が使えるのか調べるの面倒くさい● でも Verilog は書きたくないそうだ、 Chisel 3 で開発すればいいじゃないというわけで、テストコード含めて1万行ぐらいゴリゴリ書いてきた知見をお話しします6
Copyright© Fixstars GroupChisel 37
Copyright© Fixstars GroupChisel とは● Verilog しんどいから作られた(たぶん) HDL を生成するための言語○ 言語というか、 Scala の 内部 DSL○ JavaScript でいう CoffeeScript とか TypeScript■ 他にも色々あるけど、RISC-V で使われているという実績がある● 公式サイト: https://www.chisel-lang.org/○ GitHub: https://github.com/chipsalliance/chisel38
Copyright© Fixstars GroupChisel のメリット● Scala なので IDE がリッチ● テストが書きやすい● Verilog を生成できるのでどの環境でも動く● Verilogでは面倒・難しいトリッキーな書き方が容易○ 関数内でモジュールのインスタンス化○ 関数内でFFの値を変更したり、論理を動的に生成したり○ モジュール間の接続の関数化○ バルク接続が超便利● DPI-C が無くてもプログラミングやライブラリの機能を強力に使える 9
Copyright© Fixstars GroupChisel のデメリット● Scala であるためか重い○ Chisel3.6 の CIRCT でどの程度早くなるのか次第● テストが書きにくい● 出力された Verilog を人間が読むのは難しい○ Chisel で書いたモジュールを Chisel がコンパイルして生成した論理を Chisel でテスト…○ ところで Chisel には保障とかないですよね?お?■ A 社とか C 社とか I 社のツールにバグがないってわけでもないけど● メタな書き方してると割とバグ(?)を踏み抜いて悩む○ implicite やら AST が多すぎて自分のコードがバグってるのか、 Chisel がバグってるのかも分からないことが割とある● 間違えたときのエラーが不親切○ C++のメタプログラミングの様なエラーは勘弁してほしい○ 何も言わずに轟沈する V よりはマシと言えなくもない● negative reset が欲しい。切実に欲しい。10
Copyright© Fixstars GroupChisel の基本を超特急11
Copyright© Fixstars GroupChisel の開発環境Scala が開発できれば環境は何でもOK● 私の開発環境○ OS: Ubuntu 20.04■ シミュレーションに Verilator を使う場合は WSL か Linux が必要● WSL2でも FPGA の書き込みに USB を使うのが正直面倒くさいので Ubuntu マシン用意する方が楽● FIRRTL で済ませる場合は不要 (ちょっと巨大なロジックになってくると遅い)○ JDK: Java 8 (apt で入れたんだったかな?)○ sbt: 1.7.0 (apt で入れたんだったかな?)■ Scala: 2.13.8○ エディタ: VSCode■ Metals: https://scalameta.org/metals/docs/editors/vscode一昔前は IntelliJ しか Scala の開発環境はなかったが現在はVSCode で大きな不満はなく開発可能※個人の感想であり、効果・効能を保証するものではありません12
Copyright© Fixstars GroupChisel のディレクトリ構成通常は Chisel 専用のプロジェクトを作るのが筋でも面倒くさいEDA 用のファイルなども一括したディレクトリ構成は以下の落ち着きました13
Copyright© Fixstars GroupChisel のディレクトリ構成 (邪魔なディレクトリ)Scala (Metals)が色々ディレクトリを作って、非常に邪魔くさいので.vscode/settings.json で非表示にする方が良いと思います14
Copyright© Fixstars GroupChisel プロジェクトの初期化build.sbt を作成してプロジェクトの初期化(Metals 任せ)● build.sbt は以下を参考に作成(ルートディレクトリが異なる程度)● https://github.com/freechipsproject/chisel-template/blob/main/build.sbt15保存してこのようなポップアップが出たら、Import build を押せばOK
Copyright© Fixstars GroupChisel のサンプルを作ってみる16package sampleimport chisel3._import chisel3.util._class Sample extends Module {val io = IO(new Bundle {val in = Input(Bool())val out = Output(Bool())})val reg = RegInit(false.B)reg := io.inio.out := reg}
Copyright© Fixstars GroupChisel から Verilog へSample.scala に以下を追加17object Sample extends App {val dir = "rtl/chisel"// どんなオプションがあるか知りたければ、// 最初に "--help" を入れて実行するval option = Array(// "--help","-td=" + dir, // 出力ディレクトリの設定"--emission-options=disableMemRandomization,disableRegisterRandomization")(new chisel3.stage.ChiselStage).emitVerilog(new Sample,option)}
Copyright© Fixstars GroupChisel から Verilog へ18run で実行デフォルトでは chisel ディレクトリのプロジェクトが選択されていないので「project chisel」で選択ターミナルを開き、 sbt を実行するsbt は起動が遅いので、ターミナルを占有して立ち上げっぱなしにしておく※ ワンライナーで実行する場合は 「 sbt "project chisel" run 」
Copyright© Fixstars GroupChisel から Verilog へ19
Copyright© Fixstars GroupChisel から Verilog へ20同期リセットになってる
Copyright© Fixstars GroupChisel を非同期リセットにする21package sampleimport chisel3._import chisel3.util._class Sample extends Modulewith RequireAsyncReset {val io = IO(new Bundle {val in = Input(Bool())val out = Output(Bool())})val reg = RegInit(false.B)reg := io.inio.out := reg} ASIC な人でも実際安心
Copyright© Fixstars GroupChisel と Verilog の簡易比較22Verilog Chisel数値 10032’d065’h1FFFFFFFFFFFFFFFFtrue false100.U(unsigned) / 100.S (signed)0.U(32.W) / 0.S(32.W)“h1FFFFFFFFFFFFFFFF”.U(65.W)true.B false.BFF logic ff;always_ff @(posedge clk)if (!rst) ff <= 1’b0;else ff <= 1’b1;val ff = RegInit(0.U(1.W))ff := 1.U(1.W)三項演算子 c? a : b Mux(c, a, b)if - else if - else if (cond1) beginend else if (cond2) beginend else beginendwhen(cond1) {}.elsewhen(cond2) {}.otherwise {}比較演算子 a == ba != ba === ba =/= b
Copyright© Fixstars GroupChisel と Verilog の簡易比較23Verilog Chiselport 宣言 module X (input [1:0] a,output [2:0] b);val io = IO( new Bundle {val a = Input(UInt(2.W))val b = Output(UInt(3.W))})三項演算子連打 logic x;assign x = c1 ? a1:c2 ? a2:c3 ? a3:x_default;val x = WireInit( xDefault )when(c1) { x := a1 }when(c2) { x := a2 }when(c3) { x := a3 }MuxCaseというのもあるにはあるswitch 文 case (state)X:endcasewhen().elsewhen().otherwise が良いMuxLookupやswitch-is があるにはあるが…instance 化 my_module i1 (.x(x),.y(y));val i1 = Module(new MyModule)i1.io.x := xi1.io.y := y
Copyright© Fixstars GroupChisel と Verilog の簡易比較24Verilog Chisel結合 assign x = {a, b, c}; x := Cat(a, b, c)bit 取得 if (x[1]) beginendwhen( x(1) ) {}[msb: lsb] x[3: 1] x(3, 1)2次元配列 logic [7:0] array[0: 99] val array = Vec(100, UInt(8.W))1要素の長さが異なる配列の定義とアクセス簡単にはできない…と思うScala の Seq と for を使って割と簡単に記述できるval array = Seq(Wire(UInt(8.W)), Wire(UInt(16.W),...for((w, i) when( logicIndex === i.U ) {value := w}}
Copyright© Fixstars GroupChisel の Bundle今まで何度か出てきた Bundle は SystemVerilog の interface の様なものです25interface X;logic [7:0] a;logic b;endinterfaceclass X extends Bundle {val a = UInt(8.W)val b = Bool()}new Bundle {val a = UInt(8.W)val b = Bool()}SystemVerilog ChiselX という名前を付けずにインスタンスを作成する場合
Copyright© Fixstars GroupChisel の Bundle今まで何度か出てきた Bundle は SystemVerilog の interface の様なものです26interface X;logic [7:0] a;logic b;//※ modport で宣言しなくても使えるmodport o (output a,output b);modport i (input a,input b);endinterfaceclass X extends Bundle {val a = UInt(8.W)val b = Bool()}// IO として使う時val io = IO( new Bundle {val o = Output(new X)val i = Input(new X)})SystemVerilog Chisel
Copyright© Fixstars GroupChisel の Bundle今まで何度か出てきた Bundle は SystemVerilog の interface の様なものです27interface X;logic [7:0] a;logic b;modport main (output a,input b);modport secondary (input a,output b);endinterfaceclass X extends Bundle {val a = Output(UInt(8.W))val b = Input(Bool())}// IO として使う時val io = IO( new Bundle {val main = new Xval secondary = Flipped(new X)})SystemVerilog Chisel
Copyright© Fixstars GroupChisel の Bundle今まで何度か出てきた Bundle は SystemVerilog の interface の様なものです28X x;ModuleA a (.portX(x));ModuleB b (.portX(x))val a = Module( new ModuleA )val b = Module( new ModuleB )a.io.portX <> b.io.portXSystemVerilog Chisel<> を バルク 接続演算子と呼びます。:= と違い、output/input をいい感じに繋いでくれますChisel では Bundle と バルク接続 をうまく利用して記述を圧縮することが基本
Copyright© Fixstars GroupBundle間で バルク接続(1)例: 継承関係で接続したい例: AXI-Stream のサブチャネルのありなしとか29
Copyright© Fixstars GroupBundle間で バルク接続(1)viewAsSupertype で変換してからバルク接続30
Copyright© Fixstars GroupBundle間で バルク接続(1)viewAsSupertype で変換してからバルク接続31
Copyright© Fixstars GroupBundle間で バルク接続(2)例: 他人が作った Bundle と自分の Bundle が実質同じなので接続したい例: ValidIO と AXI-Stream とか32
Copyright© Fixstars GroupBundle間で バルク接続(2)DataView で Xbundle と YBundle のフィールド対応を定義し、 viewAs で変換33
Copyright© Fixstars GroupBundle間で バルク接続(2)DataView で Xbundle と YBundle のフィールド対応を定義し、 viewAs で変換34詳細は https://www.chisel-lang.org/chisel3/docs/cookbooks/dataview.html 参照
Copyright© Fixstars GroupBundle間で バルク接続(1)半月ほど前のコミット見ると、次のリリースからはこう書けるようになるみたい35https://github.com/chipsalliance/chisel3/commit/251d454a224e5a961438ba0ea41134d7da7a5992
Copyright© Fixstars GroupChisel Enum● まだ 実験段階だが、 ChiselEnum で列挙型を定義可能36
Copyright© Fixstars GroupChisel の基本 まとめ● 開発環境○ OS は Linux の実機がお勧め○ エディタは VSCode で十分● ディレクトリ構成○ EDA ツールと一緒に開発する場合の私の構成について(基本からは外れている)● Chisel の初期化○ build.sbt を書いたら後は Metals や sbt にお任せ● シンプルなデザインの作成と Verilog への変換方法○ 非同期リセットの作り方もついでに紹介● Chisel と Verilog で大きく違う基本的な構文についての比較● Chisel の Bundle に関する基本項目○ Chisel の Bundle はおおよそ SystemVerilog の interface○ Chisel のバルク接続は強力○ おまけ:supertype が実装されるらしいよ● Chisel の列挙型について37
Copyright© Fixstars GroupChisel でテスト38
Copyright© Fixstars GroupChisel でテスト39Chisel のテストは、シミュレータを操作することで値を入力したり、値が正しいかの確認を行う
Copyright© Fixstars GroupChisel でテストを作る40
Copyright© Fixstars GroupChisel でテストを作るsbt で test とタイプするとテストを実行できる以下のように[success]と出て終了する41
Copyright© Fixstars GroupChisel でテストを作るsbt で test とタイプするとテストを実行できる以下のように[success]と出て終了する42
Copyright© Fixstars GroupChisel でテストを作るit should “テスト名” test(new テストベンチモジュール) { tb => }を追加してテストを増やしていく43
Copyright© Fixstars GroupChisel でテストを作る………いや、何で失敗すんのよ波形、波形をくれ44
Copyright© Fixstars GroupChisel でテストを作る波形を取得する為に 「testOnly * – -DwriteVcd=1」を実行コマンドの意味は、全てのテスト実行する(* のワイルドカード)。オプションとしてwriteVcd=1(波形ファイルの書き出し)を渡すということ45test_run_dirに 「〇_should_●」ディレクトリがありその中に vcd ファイルが保存されるGTKWave などで波形を確認
Copyright© Fixstars GroupChisel assertion46Verilog の assertion の様に毎クロック値を確認する、というようなテストをモジュール内に書ける
Copyright© Fixstars GroupChisel assertion47Verilog の assertion の様に毎クロック値を確認する、というようなテストをモジュール内に書ける
Copyright© Fixstars GroupChisel assertion48出力される Verilog が汚くなるのはご愛敬………?何とかならない?
Copyright© Fixstars GroupChisel のテストを Verilator で実行論路規模が大きくなってくると、 FIRRTL のシミュレーションでは時間がかかりすぎて待ってられない時間がかかるな、と思ったら Verilator でシミュレーションすることを検討すると良い.withAnnotations(Seq(VerilatorBackendAnnotation))49Verilator のコンパイルに時間はかかるけど、シミュレーションは非常に早い
Copyright© Fixstars GroupVerilator がおかしくなったらVerilator が成功するはずのテストで失敗することがある- FIRRTL でテストをすると成功する- ポート名などを変更しても VCD に反映されないVerilator の VCD 波形が出ないこともよくあるsbt を閉じて、target (targetとchisel/target)とtest_run_dirを削除すると、うまくいく。何が・どれが悪いのかはよくわからない。50
Copyright© Fixstars GroupChisel でテスト メリット● 書くのが簡単○ shell script とか用意しなくても実行集計すぐできる○ 補完が効くのは偉大● 外部のライブラリなどをそのまま使える○ CRC計算の結果があってるかとか、一度ファイルに出すとかせずにライブラリ呼び出した結果を直接使える● Scala の強力な構文が色々使える○ for とか○ match とか51
Copyright© Fixstars GroupChisel でテスト デメリット● 書くのが辛い○ Verilog で言ってしまえば、テストベンチの initial 内で全部のテストを記述するようなもの○ always の様な時間の並列化や、 @(posedge 信号) みたいな記述が簡単にできない■ 時間の分岐: fork{}.join() で分岐■ 毎クロックチェック: assert○ 内部の信号に簡単にアクセスできない● マルチ ドメイン クロックのテストが辛い○ RTL 側は withClock で CDC は割と簡単に書ける○ テスト側はテストベンチのクロック単位でしか時間が進まないので CDC が書けない■ 私はテストベンチ用 モジュールでカウンタを使ってクロックを作るようなやり方で記述した● it should “” の単位でテストを実行できない○ tag というのを使えばなんかできるみたいだけど○ scala 力が足りないだけ?よくわからない● 入力がクロックの立ち下がりに同期してるのが辛い○ 信号が増えると目がバグるのでエッジをそろえないでほしい…52
Copyright© Fixstars GroupChisel でテスト まとめ● Chisel でテストする方法について○ 基本的には poke で値を突っ込んで expect で確認■ peek〇 で値として読みだすこともできます○ assert を使えば毎クロック勝手にチェック可能● Chisel のテストを Verilator で走らせる方法について○ VerilatorBackendAnnotation をつける○ よく変になるので target ディレクトリとtest_run_dir を削除して sbt 再起動● Chisel のメリット ・ デメリット○ 割とテスト書くのしんどい 53
Copyright© Fixstars Group閑話休題論理どうやって設計してる?54
Copyright© Fixstars Group論理どうやって設計してる?● VSCode + Markdown + mermaid + Draw.io +タイミングチャート清書サービス(改造)55
Copyright© Fixstars Group論理どうやって設計してる?● VSCode○ 昨今独り勝ち状態のエディタ。Atomさん…● Markdown○ いわずもがな● mermaid○ 状態遷移図作成等に利用○ GitHub で Markdown に埋め込んでそのまま表示できる○ VSCode には Markdown Preview Mermaid Support を導入すれば Markdown に組み込める■ https://marketplace.visualstudio.com/items?itemName=bierner.markdown-mermaid● Draw.io○ HTML5/JavaScript で作られた Visio みたいなもの○ VSCode では Draw.io Integration で VSCode 上で使うことができる■ https://marketplace.visualstudio.com/items?itemName=hediet.vscode-drawio○ *.drawio.svg という拡張子にして保存すれば、Markdown に組み込めて、Draw.io で編集できるので便利56
Copyright© Fixstars Group論理どうやって設計してる?● WaveDrom○ https://wavedrom.com/editor.html○ 美しいタイミング図が作れる○ 最近はこれが使われていることが多い印象■ 正直タイミング図を書くならこれ一択■ GitHub 対応してくれないかな…でも書くの面倒くさい※個人の感想です。用法容量を守って正しくお使いください57
Copyright© Fixstars Group論理どうやって設計してる?● タイミングチャート清書サービス○ 何も考えずに書ける○ https://dora.bk.tsukuba.ac.jp/~takeuchi/?%E3%82%BD%E3%83%95%E3%83%88%E3%82%A6%E3%82%A7%E3%82%A2%2F%E3%82%BF%E3%82%A4%E3%83%9F%E3%83%B3%E3%82%B0%E3%83%81%E3%83%A3%E3%83%BC%E3%83%88%E6%B8%85%E6%9B%B8%E3%82%B5%E3%83%BC%E3%83%93%E3%82%B958
Copyright© Fixstars Group論理どうやって設計してる?● タイミングチャート清書サービス(改造)○ こんな感じに2カラム化して出力ファイル名を変えれるようにしてる○ SVG の先頭にオリジナルデータが格納されてるので復元できるようにしてる○ SVG なので Markdown でそのまま表示できる。便利○ 信号名が調整しないと見切れるのは如何なものか…■ タイミグチャート清書サービス記法→WaveDrom→SVG の仕組みを作ろうと思い早や幾年59
Copyright© Fixstars GroupChisel 開発ノウハウ(あくまで個人のノウハウ)60
Copyright© Fixstars GroupFFの作り方 あれこれ61
Copyright© Fixstars GroupFFの作り方 あれこれ62
Copyright© Fixstars GroupFFの作り方 あれこれ63
Copyright© Fixstars GroupChisel と コンストラクタ と フィールド● Chisel でロジックを書くこの部分はコンストラクタ● ここにモジュールや信号なども定義していくのがチュートリアル的なスタイル○ 定義した信号などはフィールドとなり外部からアクセス可能● io.portName の様に毎回 io. を書くのが面倒になってくる○ val portName = io.portName として横着することを覚えた64
Copyright© Fixstars GroupChisel と コンストラクタ と フィールドそして悲劇は起こった65
Copyright© Fixstars GroupChisel と コンストラクタ と フィールドそして悲劇は起こった66
Copyright© Fixstars GroupChisel と コンストラクタ と フィールド● 極力 private val にするようにした● private をつけるのも面倒になって {} でくくるようになった67
Copyright© Fixstars GroupChisel と IO Bundleチュートリアルでは、入出力が反転するポートは Flipped を使って書かれるStream の様に入出力がはっきりしてる Bundle なら覚えやすいが、複雑な Bundle になってくるとどちらで反転するのかわからなくなる68val primary = new HogeBundle val secondary = Flipped(new HogeBundle)
Copyright© Fixstars GroupChisel と IO Bundle結局 SystemVerilog の modport をまねる形に落ち着いた69class HogeBundle extends Bundle {val moge = Output(略)val piyo = Input(略)}object HogeBundle {def apply() = new HogeBundledef ctrl = new HogeBundledef func = Flipped(new HogeBundle)}val ctrl = HogeBundle.ctrlval func = HogeBundle.func
Copyright© Fixstars GroupChisel ノウハウ まとめ● FFの作り方○ RegNextPair という object を作って使ってます● 内部信号にアクセスする悲劇○ private val を使いましょう○ 面倒なら { } で囲いましょう● IO Bundle の Flipped○ 結局 SystemVerilog の modport は良いスタイルだと思う70
Copyright© Fixstars Group最後に71
Copyright© Fixstars GroupChisel は救いになるか。● 個人的には Verilog よりもずっと好きだし、書いていて楽しい● 趣味用途には今日からの使用をお勧めします● 仕事に使えるかどうかは、微妙○ 万人が使える物ではない■ 非プログラマとプログラマで書きあがるコードに大きな差が確実に出る○ エラーがきつい○ 保証がないことにどう向き合うか?● 既存モジュール接続のためのグルーロジックとしては仕事に使える○ 読める程度の Verilog コードしか出てこないなら問題は何もない● 小さなロジックで社外に出ないコードなら活用可能72
Copyright© Fixstars Group最後に● Scala の資を容易に取り込めるのは強い○ 一方で、 Scala の上に構築されているが故の問題点があるのも事実● メタ プログラミング的な話もしたかったけど、時間足りないので削った○ Vivado IP を生成する話も削った● 私が思う Chisel の最大の成果は FIRRTL○ そして時代は LLVM-CIRCT へ○ 今後もっと LLVM-CIRCT を介してトランスパイルする言語が増えると面白いですね● Chisel は今後も安泰?○ RISC-V の流れ的に十分安泰○ 後はユーザー数の問題かと○ むろん、JavaScript で言う Chisel = CoffeeScript で今後 TypeScript が出てくる可能性も■ でも、 CoffeeScript は今でも俺たちの心の中で輝いてるよね?みんなぜひ Chisel を使ってみましょう!73
Copyright © Fixstars GroupThank you!お問い合わせ窓口 : [email protected]